(Created page with "var Message = {}; (function(){ /* Structure: * * Start: 'Spy': 3 * 3 base-pairs * Length: 16 bit number: 8 base-pairs * CRC32: 16 bit number: 8 base-pairs...") |
|||
Line 4: | Line 4: | ||
/* Structure: | /* Structure: | ||
* | * | ||
− | * Start: 'Spy': 3 * | + | * Start: 'Spy': 3 * 4 bases |
− | * Length: 16 bit number: 8 | + | * Pad: 'AAAA': 4 bases |
− | * CRC32: 16 bit number: 8 | + | * Subst: 1 character 1 * 4 bases |
− | * Data: '...': length * | + | * Length: 16 bit number: 8 bases |
− | * End: 'GEM': 3 * | + | * CRC32: 16 bit number: 8 bases |
+ | * Data: '...': length * 4 bases | ||
+ | * End: 'GEM': 3 * 4 bases | ||
*/ | */ | ||
− | var lengths = { | + | var headDNA = EightBit.encodeStr('Spy'), |
− | + | tailDNA = EightBit.encodeStr('GEM'), | |
− | + | padDNA = 'AAAA', | |
− | + | lengths = { | |
− | + | 'start': headDNA.length, | |
− | + | 'pad': 4, | |
− | + | 'subst': 4, | |
+ | 'len': 8, | ||
+ | 'crc': 8, | ||
+ | 'end': tailDNA.length | ||
+ | }, | ||
+ | offsets = {}, | ||
+ | subOffs = {}, | ||
+ | subBase = 'A'; | ||
+ | |||
offsets.start = 0; | offsets.start = 0; | ||
− | offsets. | + | offsets.pad = offsets.start + lengths.start; |
− | offsets. | + | offsets.subst = offsets.pad + lengths.pad; |
− | + | offsets.len = offsets.subst + lengths.subst; | |
+ | subOffs.len = 0; | ||
+ | subOffs.crc = subOffs.len + lengths.len; | ||
+ | subOffs.data = subOffs.crc + lengths.crc; | ||
var packDNA = function(dna, ext){ | var packDNA = function(dna, ext){ | ||
− | var len = dna.length, | + | var subst = 0, |
+ | len = dna.length, | ||
crc = CRC.crc16(dna), | crc = CRC.crc16(dna), | ||
− | + | lenDNA = DNA.encodeUInt(len, lengths.len), | |
− | + | crcDNA = DNA.encodeUInt(crc, lengths.crc), | |
− | + | suffixDNA = lenDNA + crcDNA + dna + tailDNA, | |
− | + | subst = DNA.Restrict.shortestAbsent(suffixDNA, subBase), | |
− | msg = | + | substDNA = DNA.encodeUInt(subst.length, 4), |
+ | msg = headDNA + padDNA + substDNA + DNA.Restrict.substitute(suffixDNA, subBase, subst); | ||
+ | |||
+ | var det = DNA.Restrict.detect(msg); | ||
+ | if(det.length > 0){ | ||
+ | throw new Error("Restriction substitution failed"); | ||
+ | } | ||
if(ext){ | if(ext){ | ||
return { | return { | ||
'msg': msg, | 'msg': msg, | ||
+ | 'subst': subst.length, | ||
'len': len, | 'len': len, | ||
'crc': crc, | 'crc': crc, | ||
− | 'dnaStart': | + | 'dnaStart': headDNA, |
− | 'dnaEnd': | + | 'dnaEnd': tailDNA, |
− | ' | + | 'dnaSubst': substDNA, |
− | 'dnaCrc': | + | 'dnaLen': lenDNA, |
+ | 'dnaCrc': crcDNA | ||
}; | }; | ||
} | } | ||
Line 48: | Line 70: | ||
var unpackDNA = function(msg, ext){ | var unpackDNA = function(msg, ext){ | ||
var dnaStart = msg.substr(offsets.start, lengths.start), | var dnaStart = msg.substr(offsets.start, lengths.start), | ||
− | + | start = EightBit.decodeStr(dnaStart), | |
+ | pad = msg.substr(offsets.pad, lengths.pad); | ||
if(start !== 'Spy'){ // start mismatch | if(start !== 'Spy'){ // start mismatch | ||
Line 55: | Line 78: | ||
} | } | ||
− | var | + | var dnaSubst = msg.substr(offsets.subst, lengths.subst), |
+ | subst = DNA.decodeUInt(dnaSubst), | ||
+ | suffixDNA = msg.substr(offsets.len), | ||
+ | suffix = DNA.Restrict.restore(suffixDNA, subBase.repeat(subst)), | ||
+ | dnaLen = suffix.substr(subOffs.len, lengths.len), | ||
len = DNA.decodeUInt(dnaLen), | len = DNA.decodeUInt(dnaLen), | ||
− | dnaCrc = | + | dnaCrc = suffix.substr(subOffs.crc, lengths.crc), |
crc = DNA.decodeUInt(dnaCrc), | crc = DNA.decodeUInt(dnaCrc), | ||
− | data = | + | data = suffix.substr(subOffs.data, len); |
if(CRC.crc16(data) !== crc){ // checksum mismatch | if(CRC.crc16(data) !== crc){ // checksum mismatch | ||
− | throw new Error('CRC mismatch: '+CRC.crc16(data)+' / '+crc); | + | throw new Error('CRC mismatch: '+CRC.crc16(data)+' / '+crc+" ("+data.length+" / "+len+")"); |
return null; | return null; | ||
} | } | ||
− | var dnaEnd = | + | var dnaEnd = suffix.substr(subOffs.data + len, lengths.end), |
− | end = | + | end = EightBit.decodeStr(dnaEnd); |
if(end !== 'GEM'){ | if(end !== 'GEM'){ | ||
Line 77: | Line 104: | ||
return { | return { | ||
'data': data, | 'data': data, | ||
+ | 'subst': subst, | ||
'len': len, | 'len': len, | ||
'crc': crc, | 'crc': crc, | ||
'dnaStart': dnaStart, | 'dnaStart': dnaStart, | ||
+ | 'dnaSubst': dnaSubst, | ||
'dnaEnd': dnaEnd, | 'dnaEnd': dnaEnd, | ||
'dnaLen': dnaLen, | 'dnaLen': dnaLen, |
Revision as of 13:16, 8 July 2016
var Message = {};
(function(){ /* Structure: * * Start: 'Spy': 3 * 4 bases * Pad: 'AAAA': 4 bases * Subst: 1 character 1 * 4 bases * Length: 16 bit number: 8 bases * CRC32: 16 bit number: 8 bases * Data: '...': length * 4 bases * End: 'GEM': 3 * 4 bases */ var headDNA = EightBit.encodeStr('Spy'), tailDNA = EightBit.encodeStr('GEM'), padDNA = 'AAAA', lengths = { 'start': headDNA.length, 'pad': 4, 'subst': 4, 'len': 8, 'crc': 8, 'end': tailDNA.length }, offsets = {}, subOffs = {}, subBase = 'A';
offsets.start = 0; offsets.pad = offsets.start + lengths.start; offsets.subst = offsets.pad + lengths.pad; offsets.len = offsets.subst + lengths.subst; subOffs.len = 0; subOffs.crc = subOffs.len + lengths.len; subOffs.data = subOffs.crc + lengths.crc;
var packDNA = function(dna, ext){ var subst = 0, len = dna.length, crc = CRC.crc16(dna), lenDNA = DNA.encodeUInt(len, lengths.len), crcDNA = DNA.encodeUInt(crc, lengths.crc), suffixDNA = lenDNA + crcDNA + dna + tailDNA, subst = DNA.Restrict.shortestAbsent(suffixDNA, subBase), substDNA = DNA.encodeUInt(subst.length, 4), msg = headDNA + padDNA + substDNA + DNA.Restrict.substitute(suffixDNA, subBase, subst);
var det = DNA.Restrict.detect(msg); if(det.length > 0){ throw new Error("Restriction substitution failed"); }
if(ext){ return { 'msg': msg, 'subst': subst.length, 'len': len, 'crc': crc, 'dnaStart': headDNA, 'dnaEnd': tailDNA, 'dnaSubst': substDNA, 'dnaLen': lenDNA, 'dnaCrc': crcDNA }; }
return msg; };
var unpackDNA = function(msg, ext){ var dnaStart = msg.substr(offsets.start, lengths.start), start = EightBit.decodeStr(dnaStart), pad = msg.substr(offsets.pad, lengths.pad);
if(start !== 'Spy'){ // start mismatch throw new Error("Start mismatch: '"+start+"' / 'Spy'"); return null; }
var dnaSubst = msg.substr(offsets.subst, lengths.subst), subst = DNA.decodeUInt(dnaSubst), suffixDNA = msg.substr(offsets.len), suffix = DNA.Restrict.restore(suffixDNA, subBase.repeat(subst)), dnaLen = suffix.substr(subOffs.len, lengths.len), len = DNA.decodeUInt(dnaLen), dnaCrc = suffix.substr(subOffs.crc, lengths.crc), crc = DNA.decodeUInt(dnaCrc), data = suffix.substr(subOffs.data, len);
if(CRC.crc16(data) !== crc){ // checksum mismatch throw new Error('CRC mismatch: '+CRC.crc16(data)+' / '+crc+" ("+data.length+" / "+len+")"); return null; }
var dnaEnd = suffix.substr(subOffs.data + len, lengths.end), end = EightBit.decodeStr(dnaEnd);
if(end !== 'GEM'){ throw new Error("End mismatch: '"+end+"' / 'GEM'"); return null; }
if(ext){ return { 'data': data, 'subst': subst, 'len': len, 'crc': crc, 'dnaStart': dnaStart, 'dnaSubst': dnaSubst, 'dnaEnd': dnaEnd, 'dnaLen': dnaLen, 'dnaCrc': dnaCrc }; }
return data; };
Message = { 'packDNA': packDNA, 'unpackDNA': unpackDNA }; })();