blob: 6d12b87a413f61956bfbf59571b630c528e38b9d [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
/**
* @fileoverview Utilities for manipulating types.
* @private
*/
var Type = require('./type.js');
var kind = require('./kind.js');
// TODO(bprosnitz) Should we add other helpers? Or is it better just to directly
// create the types in js?
/**
* @summary Namespace of pre-defined VDL Types.
* @description Namespace of pre-defined VDL Types.
* @namespace
* @memberof module:vanadium.vdl
*/
var types = {
/**
* @type {module:vanadium.vdl.Type}
* @const
*/
ANY: primitiveType(kind.ANY),
/**
* @type {module:vanadium.vdl.Type}
* @const
*/
BOOL: primitiveType(kind.BOOL),
/**
* @type {module:vanadium.vdl.Type}
* @const
*/
BYTE: primitiveType(kind.BYTE),
/**
* @type {module:vanadium.vdl.Type}
* @const
*/
UINT16: primitiveType(kind.UINT16),
/**
* @type {module:vanadium.vdl.Type}
* @const
*/
UINT32: primitiveType(kind.UINT32),
/**
* @type {module:vanadium.vdl.Type}
* @const
*/
UINT64: primitiveType(kind.UINT64),
/**
* @type {module:vanadium.vdl.Type}
* @const
*/
INT8: primitiveType(kind.INT8),
/**
* @type {module:vanadium.vdl.Type}
* @const
*/
INT16: primitiveType(kind.INT16),
/**
* @type {module:vanadium.vdl.Type}
* @const
*/
INT32: primitiveType(kind.INT32),
/**
* @type {module:vanadium.vdl.Type}
* @const
*/
INT64: primitiveType(kind.INT64),
/**
* @type {module:vanadium.vdl.Type}
* @const
*/
FLOAT32: primitiveType(kind.FLOAT32),
/**
* @type {module:vanadium.vdl.Type}
* @const
*/
FLOAT64: primitiveType(kind.FLOAT64),
/**
* @type {module:vanadium.vdl.Type}
* @const
*/
COMPLEX64: primitiveType(kind.COMPLEX64),
/**
* @type {module:vanadium.vdl.Type}
* @const
*/
COMPLEX128: primitiveType(kind.COMPLEX128),
/**
* @type {module:vanadium.vdl.Type}
* @const
*/
STRING: primitiveType(kind.STRING),
/**
* @type {module:vanadium.vdl.Type}
* @const
*/
TYPEOBJECT: Type.prototype._type // So that === works for types.TypeObject
};
/**
* @type {module:vanadium.vdl.Type}
* @const
*/
types.ERROR = defineOptionalErrorType();
/**
* @type {module:vanadium.vdl.Type}
* @const
*/
types.JSVALUE = defineJSValueType();
module.exports = types;
function defineOptionalErrorType() {
var nilErrorType = new Type();
// TODO(bprosnitz) Should we add an error constructor so error objects have
// the same prototype? (this will be the case once this is generated by VDL as
// well)
var retryCodeType = new Type();
retryCodeType.name = '';
retryCodeType.kind = kind.ENUM;
retryCodeType.labels = [
'NoRetry',
'RetryConnection',
'RetryRefetch',
'RetryBackoff'
];
var paramListType = new Type();
paramListType.name = '';
paramListType.kind = kind.LIST;
paramListType.elem = types.ANY;
var errorType = new Type();
errorType.name = 'error';
errorType.kind = kind.STRUCT;
errorType.fields = [
{
name: 'Id',
type: types.STRING
},
{
name: 'RetryCode',
type: retryCodeType
},
{
name: 'Msg',
type: types.STRING
},
{
name: 'ParamList',
type: paramListType
}
];
nilErrorType.name = '';
nilErrorType.kind = kind.OPTIONAL;
nilErrorType.elem = errorType;
return nilErrorType;
}
// The JSValueType is a special type for JavaScript. Services will default to
// sending and receiving this type when they do not specify a type in their
// service signature.
// TODO(alexfandrianto): We are still use types.ANY instead of types.JSVALUE.
// TODO(alexfandrianto): We should consider moving this type into VDL.
// See the issue: https://github.com/veyron/release-issues/issues/760
// Warning: In the rare case that someone defines their own JSValue, they will
// not have the expected behavior in encode/decode/canonicalize because JSValue
// is heavily special-cased.
function defineJSValueType() {
var JSValueType = new Type();
var EmptyStruct = new Type();
var ByteList = new Type();
var JSValueList = new Type();
var JSKeyValueList = new Type();
var JSKeyValuePair = new Type();
var JSStringValueList = new Type();
var JSStringValuePair = new Type();
// Fill JSValue
JSValueType.name = 'JSValue';
JSValueType.kind = kind.UNION;
JSValueType.fields = [
{
name: 'Null',
type: EmptyStruct
},
{
name: 'Boolean',
type: types.BOOL
},
{
name: 'Number',
type: types.FLOAT64
},
{
name: 'String',
type: types.STRING
},
{
name: 'Bytes',
type: ByteList
},
{
name: 'List',
type: JSValueList
},
{
name: 'Set',
type: JSValueList
},
{
name: 'Map',
type: JSKeyValueList
},
{
name: 'Object',
type: JSStringValueList
}
];
// Define the rest of EmptyStruct
// Add a name, since VDL does not allow unnamed, empty structs.
EmptyStruct.kind = kind.STRUCT;
EmptyStruct.fields = [];
EmptyStruct.name = 'EmptyStruct';
// Define the rest of ByteList
ByteList.kind = kind.LIST;
ByteList.elem = types.BYTE;
// Define the rest of JSValueList
JSValueList.kind = kind.LIST;
JSValueList.elem = types.ANY;
// Define the rest of JSKeyValueList
JSKeyValueList.kind = kind.LIST;
JSKeyValueList.elem = JSKeyValuePair;
// Define the rest of JSKeyValuePair
JSKeyValuePair.kind = kind.STRUCT;
JSKeyValuePair.fields = [
{
name: 'Key',
type: types.ANY
},
{
name: 'Value',
type: types.ANY
}
];
// Define the rest of JSStringValueList
JSStringValueList.kind = kind.LIST;
JSStringValueList.elem = JSStringValuePair;
// Define the rest of JSStringValuePair
JSStringValuePair.kind = kind.STRUCT;
JSStringValuePair.fields = [
{
name: 'Key',
type: types.STRING
},
{
name: 'Value',
type: types.ANY
}
];
return JSValueType;
}
// Primitive types only need a kind. They have an empty name by default.
function primitiveType(kind) {
var prim = new Type();
prim.kind = kind;
return prim;
}