Skip to content

Commit

Permalink
feat(Value)!: attempt to find kind when kind field is absent (#10)
Browse files Browse the repository at this point in the history
  • Loading branch information
callmehiphop committed Jun 1, 2021
1 parent a9de3e1 commit 2ecd42e
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 9 deletions.
54 changes: 45 additions & 9 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,25 +57,53 @@ export interface ListValue {
values?: Value[];
}

/**
* Valid `kind` types
*/
enum Kind {
Struct = 'structValue',
List = 'listValue',
Number = 'numberValue',
String = 'stringValue',
Bool = 'boolValue',
Null = 'nullValue'
}

const toString = Object.prototype.toString;

const encoders = {
[typeOf({})]: v => wrap('structValue', struct.encode(v)),
[typeOf([])]: v => wrap('listValue', list.encode(v)),
[typeOf(0)]: v => wrap('numberValue', v),
[typeOf('')]: v => wrap('stringValue', v),
[typeOf(true)]: v => wrap('boolValue', v),
[typeOf(null)]: () => wrap('nullValue', 0)
[typeOf({})]: v => wrap(Kind.Struct, struct.encode(v)),
[typeOf([])]: v => wrap(Kind.List, list.encode(v)),
[typeOf(0)]: v => wrap(Kind.Number, v),
[typeOf('')]: v => wrap(Kind.String, v),
[typeOf(true)]: v => wrap(Kind.Bool, v),
[typeOf(null)]: () => wrap(Kind.Null, 0)
};

function typeOf(value: JsonValue): string {
return toString.call(value);
}

function wrap(kind: keyof Value, value): Value {
function wrap(kind: Kind, value): Value {
return {kind, [kind]: value};
}

function getKind(value: Value): string | null {
if (value.kind) {
return value.kind;
}

const validKinds = Object.values(Kind);

for (const kind of validKinds) {
if (value.hasOwnProperty(kind)) {
return kind;
}
}

return null;
}

/**
* Used to encode/decode {@link Value} objects.
*/
Expand All @@ -97,19 +125,27 @@ export const value = {
/**
* Decodes a protobuf {@link Value} into a JSON value.
*
* @throws {TypeError} If unable to determine value `kind`.
*
* @param {Value} value the protobuf value.
* @returns {*}
*/
decode(value: Value): JsonValue {
switch(value.kind) {
const kind = getKind(value);

if (!kind) {
throw new TypeError(`Unable to determine kind for "${value}".`);
}

switch(kind) {
case 'listValue':
return list.decode(value.listValue);
case 'structValue':
return struct.decode(value.structValue);
case 'nullValue':
return null;
default:
return value[value.kind] as JsonValue;
return value[kind] as JsonValue;
}
}
};
Expand Down
9 changes: 9 additions & 0 deletions test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,15 @@ test('value.decode - multiple values', t => {
t.is(actual, 'foo');
});

test('value.decode - no kind', t => {
const encodedValue = {
stringValue: 'foo'
};

const actual = value.decode(encodedValue);
t.is(actual, 'foo');
});

test('list.encode', t => {
const actual = list.encode(arr);
t.deepEqual(actual, listValue);
Expand Down

0 comments on commit 2ecd42e

Please sign in to comment.