make Checkables work

This commit is contained in:
Florian Dold 2016-01-05 20:09:15 +01:00
parent 9dc0d89118
commit 7b2c566cad
3 changed files with 103 additions and 31 deletions

View File

@ -27,41 +27,81 @@
namespace Checkable { namespace Checkable {
let chkSym = Symbol("checkable"); let chkSym = Symbol("checkable");
function checkNumber(target, prop) { function checkNumber(target, prop): any {
return true; if ((typeof target) !== "number") {
throw Error("number expected for " + prop.propertyKey);
}
return target;
} }
function checkString(target, prop) { function checkString(target, prop): any {
return true; if (typeof target !== "string") {
throw Error("string expected for " + prop.propertyKey);
}
return target;
}
function checkValue(target, prop): any {
let type = prop.type;
if (!type) {
throw Error("assertion failed");
}
let v = target;
if (!v || typeof v !== "object") {
throw Error("expected object for " + prop.propertyKey);
}
let props = type.prototype[chkSym].props;
let remainingPropNames = new Set(Object.getOwnPropertyNames(v));
let obj = new type();
for (let prop of props) {
if (!remainingPropNames.has(prop.propertyKey)) {
throw Error("Property missing: " + prop.propertyKey);
}
if (!remainingPropNames.delete(prop.propertyKey)) {
throw Error("assertion failed");
}
let propVal = v[prop.propertyKey];
obj[prop.propertyKey] = prop.checker(propVal, prop);
}
if (remainingPropNames.size != 0) {
throw Error("superfluous properties " + JSON.stringify(Array.from(
remainingPropNames.values())));
}
return obj;
} }
export function Class(target) { export function Class(target) {
target.checked = (v) => { target.checked = (v) => {
let props = target.prototype[chkSym].props; return checkValue(v, {
console.log("hello, world"); propertyKey: "(root)",
let remainingPropNames = new Set(Object.getOwnPropertyNames(v)); type: target,
checker: checkValue
for (let prop of props) { });
remainingPropNames.delete(prop);
console.log("prop", prop);
}
if (remainingPropNames.size != 0) {
throw Error("superfluous properties " + JSON.stringify(remainingPropNames.values()));
}
}; };
return target; return target;
} }
export function Value(type) { export function Value(type) {
function deco(target) { function deco(target: Object, propertyKey: string | symbol): void {
let chk = target[chkSym];
if (!chk) {
chk = {props: []};
target[chkSym] = chk;
}
chk.props.push({
propertyKey: propertyKey,
checker: checkValue,
type: type
});
} }
return deco; return deco;
} }
export function List(type) { export function List(type) {
function deco(target) { function deco(target: Object, propertyKey: string | symbol): void {
throw Error("not implemented");
} }
return deco; return deco;

View File

@ -28,8 +28,6 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r; return c > 3 && r && Object.defineProperty(target, key, r), r;
}; };
class MyClass {
}
let AmountJson = class { let AmountJson = class {
}; };
__decorate([ __decorate([
@ -44,6 +42,26 @@ __decorate([
AmountJson = __decorate([ AmountJson = __decorate([
Checkable.Class Checkable.Class
], AmountJson); ], AmountJson);
let CoinPaySig = class {
};
__decorate([
Checkable.String
], CoinPaySig.prototype, "coin_sig", void 0);
__decorate([
Checkable.String
], CoinPaySig.prototype, "coin_pub", void 0);
__decorate([
Checkable.String
], CoinPaySig.prototype, "ub_sig", void 0);
__decorate([
Checkable.String
], CoinPaySig.prototype, "denom_pub", void 0);
__decorate([
Checkable.Value(AmountJson)
], CoinPaySig.prototype, "f", void 0);
CoinPaySig = __decorate([
Checkable.Class
], CoinPaySig);
/** /**
* See http://api.taler.net/wallet.html#general * See http://api.taler.net/wallet.html#general
*/ */

View File

@ -26,14 +26,6 @@
/// <reference path="../decl/chrome/chrome.d.ts" /> /// <reference path="../decl/chrome/chrome.d.ts" />
"use strict"; "use strict";
class MyClass {
value: number;
fraction: number;
currency: string;
}
@Checkable.Class @Checkable.Class
class AmountJson { class AmountJson {
@Checkable.Number @Checkable.Number
@ -48,6 +40,27 @@ class AmountJson {
static check: (v: any) => AmountJson; static check: (v: any) => AmountJson;
} }
@Checkable.Class
class CoinPaySig {
@Checkable.String
coin_sig: string;
@Checkable.String
coin_pub: string;
@Checkable.String
ub_sig: string;
@Checkable.String
denom_pub: string;
@Checkable.Value(AmountJson)
f: AmountJson;
static check: (v: any) => CoinPaySig;
}
interface AmountJson_interface { interface AmountJson_interface {
value: number; value: number;
fraction: number fraction: number
@ -93,7 +106,8 @@ interface Contract {
transaction_id: number; transaction_id: number;
} }
interface CoinPaySig {
interface CoinPaySig_interface {
coin_sig: string; coin_sig: string;
coin_pub: string; coin_pub: string;
ub_sig: string; ub_sig: string;
@ -117,7 +131,7 @@ interface Reserve {
} }
type PayCoinInfo = Array<{ updatedCoin: Db.Coin, sig: CoinPaySig }>; type PayCoinInfo = Array<{ updatedCoin: Db.Coin, sig: CoinPaySig_interface }>;
/** /**
@ -180,7 +194,7 @@ function signDeposit(db: IDBDatabase,
EddsaPrivateKey.fromCrock(cd.coin.coinPriv)) EddsaPrivateKey.fromCrock(cd.coin.coinPriv))
.toCrock(); .toCrock();
let s: CoinPaySig = { let s: CoinPaySig_interface = {
coin_sig: coinSig, coin_sig: coinSig,
coin_pub: cd.coin.coinPub, coin_pub: cd.coin.coinPub,
ub_sig: cd.coin.denomSig, ub_sig: cd.coin.denomSig,