Skip to content

Commit

Permalink
Non-immediate: Add map type and associated tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
ethan7g committed Mar 19, 2019
1 parent 63cd301 commit 5453a0c
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 1 deletion.
16 changes: 16 additions & 0 deletions lib/protospec.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,22 @@ const importAll = (data) => {
options.of = parsedSchemas[options.of]
}

if (options.hasOwnProperty('key')) {
if (!types.hasOwnProperty(options.key)) throw new Error('Type \'' + options.key + '\' does not exist. (:' + i + ')')

options.key = {
'type': types[options.key]
}
}

if (options.hasOwnProperty('value')) {
if (!types.hasOwnProperty(options.value)) throw new Error('Type \'' + options.value + '\' does not exist. (:' + i + ')')

options.value = {
'type': types[options.value]
}
}

Object.assign(elementDefinition, options)
}

Expand Down
2 changes: 1 addition & 1 deletion lib/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const fs = require('fs')

const types = {}

const typeNames = ['int', 'uint', 'varint', 'float', 'double', 'boolean', 'string', 'buffer', 'list', 'instance']
const typeNames = ['int', 'uint', 'varint', 'float', 'double', 'boolean', 'string', 'buffer', 'list', 'map', 'instance']

for (let i = 0; i < typeNames.length; i++) {
types[typeNames[i]] = require(path.join(__dirname, 'types', typeNames[i] + '.js'))
Expand Down
72 changes: 72 additions & 0 deletions lib/types/map.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
const path = require('path')

const Schema = require(path.join(__dirname, '..', '..', 'model', 'Schema.js'))
const list = require(path.join(__dirname, 'list.js'))

const schemaCache = new Map()

const genMapSchema = (data) => {
if (schemaCache.has(data)) {
return schemaCache.get(data)
}
else {
const generated = new Schema([
{
'name': 'pairs',
'type': list,
'of': new Schema([
Object.assign(data.key, {
'name': 'key'
}),
Object.assign(data.value, {
'name': 'value'
})
])
}
])

schemaCache.set(data, generated)

return generated
}
}

module.exports = {
'parse': (buf, from, data) => {
if (buf.length - from < 1) {
return {
'hadUnderflow': true
}
}

const mapSchema = genMapSchema(data)

const parseResult = mapSchema.parse(buf, from, {
'returnDetails': true
})

if (parseResult.hadUnderflow) {
return {
'hadUnderflow': true
}
}

const parsedMap = new Map(parseResult.data.pairs.map((pair) => [pair.key, pair.value]))

return {
'readBytes': parseResult.finishedIndex - from,
'data': parsedMap,
'hadUnderflow': false
}
},
'serialize': (value, data) => {
const mapSchema = genMapSchema(data)

return mapSchema.build({
'pairs': Array.from(value).map((entry) => new Object({
'key': entry[0],
'value': entry[1]
}))
})
}
}
52 changes: 52 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,58 @@ w.add('Instance type functionality', (result) => {
result(true, 'Validated built data.')
})

w.add('Map type functionality', (result) => {
const mapSchema = new Schema([
{
'name': 'info',
'type': types.map,
'key': {
'type': types.string
},
'value': {
'type': types.string
}
}
])

const testData = {
'info': new Map([
['name', 'Person A'],
['location', 'Earth'],
['status', 'online']
])
}

const built = mapSchema.build(testData)

assert.deepStrictEqual(testData, mapSchema.parse(built))

result(true, 'Validated built data.')
})

w.add('Map protospec functionality', (result) => {
const mapSchema = protospec.importAll(`
def infoData
map info key=string;value=string
`).infoData

const testData = {
'info': new Map([
['name', 'Person A'],
['location', 'Earth'],
['status', 'online']
])
}

const built = mapSchema.build(testData)

assert.deepStrictEqual(testData, mapSchema.parse(built))

result(true, 'Validated built data. (Protospec success!)')
})

w.test()

process.stdin.on('data', () => {})

0 comments on commit 5453a0c

Please sign in to comment.