You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
121 lines
3.3 KiB
121 lines
3.3 KiB
'use strict'; |
|
|
|
/*eslint-disable max-len*/ |
|
|
|
var YAMLException = require('./exception'); |
|
var Type = require('./type'); |
|
|
|
|
|
function compileList(schema, name) { |
|
var result = []; |
|
|
|
schema[name].forEach(function (currentType) { |
|
var newIndex = result.length; |
|
|
|
result.forEach(function (previousType, previousIndex) { |
|
if (previousType.tag === currentType.tag && |
|
previousType.kind === currentType.kind && |
|
previousType.multi === currentType.multi) { |
|
|
|
newIndex = previousIndex; |
|
} |
|
}); |
|
|
|
result[newIndex] = currentType; |
|
}); |
|
|
|
return result; |
|
} |
|
|
|
|
|
function compileMap(/* lists... */) { |
|
var result = { |
|
scalar: {}, |
|
sequence: {}, |
|
mapping: {}, |
|
fallback: {}, |
|
multi: { |
|
scalar: [], |
|
sequence: [], |
|
mapping: [], |
|
fallback: [] |
|
} |
|
}, index, length; |
|
|
|
function collectType(type) { |
|
if (type.multi) { |
|
result.multi[type.kind].push(type); |
|
result.multi['fallback'].push(type); |
|
} else { |
|
result[type.kind][type.tag] = result['fallback'][type.tag] = type; |
|
} |
|
} |
|
|
|
for (index = 0, length = arguments.length; index < length; index += 1) { |
|
arguments[index].forEach(collectType); |
|
} |
|
return result; |
|
} |
|
|
|
|
|
function Schema(definition) { |
|
return this.extend(definition); |
|
} |
|
|
|
|
|
Schema.prototype.extend = function extend(definition) { |
|
var implicit = []; |
|
var explicit = []; |
|
|
|
if (definition instanceof Type) { |
|
// Schema.extend(type) |
|
explicit.push(definition); |
|
|
|
} else if (Array.isArray(definition)) { |
|
// Schema.extend([ type1, type2, ... ]) |
|
explicit = explicit.concat(definition); |
|
|
|
} else if (definition && (Array.isArray(definition.implicit) || Array.isArray(definition.explicit))) { |
|
// Schema.extend({ explicit: [ type1, type2, ... ], implicit: [ type1, type2, ... ] }) |
|
if (definition.implicit) implicit = implicit.concat(definition.implicit); |
|
if (definition.explicit) explicit = explicit.concat(definition.explicit); |
|
|
|
} else { |
|
throw new YAMLException('Schema.extend argument should be a Type, [ Type ], ' + |
|
'or a schema definition ({ implicit: [...], explicit: [...] })'); |
|
} |
|
|
|
implicit.forEach(function (type) { |
|
if (!(type instanceof Type)) { |
|
throw new YAMLException('Specified list of YAML types (or a single Type object) contains a non-Type object.'); |
|
} |
|
|
|
if (type.loadKind && type.loadKind !== 'scalar') { |
|
throw new YAMLException('There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.'); |
|
} |
|
|
|
if (type.multi) { |
|
throw new YAMLException('There is a multi type in the implicit list of a schema. Multi tags can only be listed as explicit.'); |
|
} |
|
}); |
|
|
|
explicit.forEach(function (type) { |
|
if (!(type instanceof Type)) { |
|
throw new YAMLException('Specified list of YAML types (or a single Type object) contains a non-Type object.'); |
|
} |
|
}); |
|
|
|
var result = Object.create(Schema.prototype); |
|
|
|
result.implicit = (this.implicit || []).concat(implicit); |
|
result.explicit = (this.explicit || []).concat(explicit); |
|
|
|
result.compiledImplicit = compileList(result, 'implicit'); |
|
result.compiledExplicit = compileList(result, 'explicit'); |
|
result.compiledTypeMap = compileMap(result.compiledImplicit, result.compiledExplicit); |
|
|
|
return result; |
|
}; |
|
|
|
|
|
module.exports = Schema;
|
|
|