All files / src/types/keyman-touch-layout keyman-touch-layout-file-reader.ts

100% Statements 79/79
100% Branches 22/22
100% Functions 2/2
100% Lines 79/79

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 791x 1x 1x 1x 1x 1x 7x 7x 7x 7x 1x 1x 1x 1x 1x 1x 1x 1x 7x 7x 7x 7x 7258x 7258x 7258x 2x 1x 1x 1x 1x 2x 2x 7256x 7256x 7256x 7258x 383x 16x 16x 16x 16x 367x 367x 1x 1x 1x 1x 367x 367x 6873x 7258x 4x 4x 4x 6869x 6869x 7x 1x 1x 1x 1x 1x 1x 1x 1x 7x 7x 7x 1x 1x 3x 1x 1x 1x 1x 3x 1x 1x 1x
import { TouchLayout } from "@keymanapp/common-types";
import TouchLayoutFile = TouchLayout.TouchLayoutFile;
import { SchemaValidators } from '@keymanapp/common-types';
 
export class TouchLayoutFileReader {
  public read(source: Uint8Array): TouchLayoutFile {
    const decoder = new TextDecoder('utf-8', {fatal:true, ignoreBOM: true});
    let sourceString: string;
    try {
      sourceString = decoder.decode(source);
    /* c8 ignore next 7 */
    } catch(e) {
      if(e instanceof TypeError) {
        // TODO: Do we want to do something else with this?
        throw e;
      }
      throw e;
    }
 
    let result: TouchLayoutFile;
    try {
      result = JSON.parse(sourceString, function(key, value) {
        // `row.id` should be number, but may have been stringified; we use
        // presence of `key` property to recognise this as a `TouchLayoutRow`.
        if(this.key && key == 'id' && typeof value == 'string') {
          const newValue = parseInt(value, 10);
          /* c8 ignore next 3 */
          if(isNaN(newValue)) {
            throw new TypeError(`Invalid row.id: "${value}"`);
          }
          return newValue;
        }
 
        // `key.width`, `key.pad`, `key.sp` should be number, but may have been
        // stringified
        if(key == 'width' || key == 'pad' || key == 'sp') {
          if(value === '') {
            // Empty string is equivalent to not present, so fall back to
            // default value
            return undefined;
          }
 
          const newValue = parseInt(value, 10);
          /* c8 ignore next 3 */
          if(isNaN(newValue)) {
            throw new TypeError(`Invalid [sub]key.${key}: "${value}"`);
          }
          return newValue;
        }
 
        if(Array.isArray(value) && value.length == 0) {
          // Delete empty arrays
          return undefined;
        }
 
        return value;
      });
    /* c8 ignore next 7 */
    } catch(e) {
      if(e instanceof SyntaxError) {
        // TODO: Do we want to do something else with this?
        throw e;
      }
      throw e;
    }
 
    return result;
  }
 
  public validate(source: TouchLayoutFile): void {
    if(!SchemaValidators.default.touchLayoutClean(source))
    /* c8 ignore next 3 */
    {
      throw new Error(JSON.stringify((<any>SchemaValidators.default.touchLayoutClean).errors));
    }
  }
 
 
};