|
7 | 7 | * @license MIT |
8 | 8 | */ |
9 | 9 |
|
10 | | -import { readLife106String, isLife106String, writeLife106String, Life106DecodedData, Life106EncodingData } from "./formats/file/life106" |
11 | | -import { readPlaintextString, isPlaintextString, PlaintextDecodedData, PlaintextMatrixWriteData, PlaintextCoordinateWriteData, writePlaintextString } from "./formats/file/plaintext" |
12 | | -import { RLECoordinateEncodingData, RLEDecodedData, RLEMatrixEncodingData, isRLEString, readRLEString, writeRLEString } from "./formats/file/rle" |
13 | | -import { Life105DecodedData, isLife105String, readLife105String } from "./formats/file/life105" |
14 | 10 | import { readLifeRule, makeLifeRule, isValidLifeRule, getLifeRuleFormat } from "./formats/rule" |
| 11 | +import { readLifeString, writeLifeString, isLifeStringFormat, getLifeStringFormat } from "./formats/file" |
15 | 12 |
|
16 | 13 | export { LifeRuleData, CONWAY_LIFE_RULE_DATA } from "./formats/rule/ruleData" |
17 | 14 | export { readLifeRule, makeLifeRule, isValidLifeRule, getLifeRuleFormat } from "./formats/rule" |
18 | | - |
19 | | - |
20 | | - |
21 | | -type SupportedLifeLikeFormats = "life 1.06" | "life 1.05" | "plaintext" | "rle" |
22 | | - |
23 | | -/** |
24 | | - * Read a life string |
25 | | - * |
26 | | - * A life string can be in either one of these formats. |
27 | | - * |
28 | | - * [Life 1.05](https://conwaylife.com/wiki/Life_1.05): |
29 | | - * represented by the string "life 1.05" |
30 | | - * |
31 | | - * [Life 1.06](https://conwaylife.com/wiki/Life_1.06): |
32 | | - * represented by the string "life 1.06" |
33 | | - * |
34 | | - * [Plaintext](https://conwaylife.com/wiki/Plaintext): |
35 | | - * represented by the string "plaintext" |
36 | | - * |
37 | | - * [Run-Length Encoded (RLE)](https://conwaylife.com/wiki/Run_Length_Encoded). |
38 | | - * represented by the string "rle" |
39 | | - * |
40 | | - * @note Usually these files are generated by a Life-Like program, such as Golly or XLife, |
41 | | - * or by a library such as llcacodec. However, they can be written by hand if you so please. |
42 | | - * |
43 | | - * The output of the given data object is based on which one of the formats is parsed. However, all returned data |
44 | | - * is guaranteed to have 2 keys: "format" and "liveCoordinates". |
45 | | - * |
46 | | - * The parsed format can be found with the "format" key, |
47 | | - * which will either have a value of "plaintext", "life 1.06", "life 1.05", or "rle" corresponding with the given life string's format. |
48 | | - * The layout of the parsed data can then be determined by finding the value of the "format" key. |
49 | | - * |
50 | | - * "liveCoordinates" will be a 2D vector array in [x, y] format where each entry represents a live cell. |
51 | | - * x and y are guaranteed to be integers. |
52 | | - * x is positive to the right and negative approaching the left, and y is positive approaching north and |
53 | | - * negative approaching south. This may be good to take note of if your program assumes that positive |
54 | | - * y approaches south, such as in a "row" and "column" layout. |
55 | | - * |
56 | | - * The particulars of each data format is out of the scope of this little docstring, |
57 | | - * and can be found in DOCUMENTATION.md in the llcacodec repository. This documentation |
58 | | - * could also be found online [here](https://www.github.com/cobyj33/llcacodec/blob/master/DOCUMENTATION.md) |
59 | | - * |
60 | | - * @param data The life string to parse for data |
61 | | - * @param format Optional parameter. Defaults to "" if no parameter is passed. This is the format |
62 | | - * used by readLifeString to parse the data. format can equal either "life 1.06", "life 1.05", |
63 | | - * "plaintext", "rle", or "". If format equals "", then readLifeString will attempt to detect |
64 | | - * the format of the provided data. If undefined is passed, an error is thrown |
65 | | - * |
66 | | - * @throws 1. If there is an error parsing the given life string in a given format. |
67 | | - * 2. If there is an error finding the life string's format. |
68 | | - * 3. If the passed format is undefined. |
69 | | - */ |
70 | | -export function readLifeString(data: string, format: "plaintext"): PlaintextDecodedData |
71 | | -export function readLifeString(data: string, format: "life 1.06"): Life106DecodedData |
72 | | -export function readLifeString(data: string, format: "rle"): RLEDecodedData |
73 | | -export function readLifeString(data: string, format: "life 1.05"): Life105DecodedData |
74 | | -export function readLifeString(data: string): Life106DecodedData | PlaintextDecodedData | RLEDecodedData | Life105DecodedData |
75 | | -export function readLifeString(data: string, format: SupportedLifeLikeFormats | "" = ""): Life106DecodedData | PlaintextDecodedData | RLEDecodedData | Life105DecodedData { |
76 | | - if (format === undefined) { |
77 | | - throw new Error("[llcacodec]: Cannot parse undefined life file") |
78 | | - } |
79 | | - |
80 | | - const foundFormat = format === "" ? getLifeStringFormat(data) : format; |
81 | | - switch (foundFormat) { |
82 | | - case "plaintext": return readPlaintextString(data); |
83 | | - case "life 1.06": return readLife106String(data); |
84 | | - case "rle": return readRLEString(data); |
85 | | - case "life 1.05": return readLife105String(data); |
86 | | - case "": throw new Error(`[llcacodecjs] Could not read life file: matching life file format could not be found`) |
87 | | - } |
88 | | -} |
89 | | - |
90 | | -/** |
91 | | - * Assert whether a life string conforms to a given format |
92 | | - * |
93 | | - * Note that just because isLifeStringFormat returns true does NOT mean that readLifeString will not throw an error when called with the given life string. |
94 | | - * isLifeStringFormat does not confirm if the passed data is valid. It only tries to detect if the given life string |
95 | | - * conforms to a format by searching for required headers and sequences in the string. |
96 | | - * |
97 | | - * @param data The life string to test |
98 | | - * @param format The format to test conformity against the given life string with. |
99 | | - * Can either be "plaintext", "life 1.05", "life 1.06", or "plaintext" |
100 | | - * @returns Whether the given life string conforms with the given format |
101 | | - */ |
102 | | -export function isLifeStringFormat(data: string, format: SupportedLifeLikeFormats): boolean { |
103 | | - switch (format) { |
104 | | - case "life 1.06": return isLife106String(data); |
105 | | - case "life 1.05": return isLife105String(data); |
106 | | - case "plaintext": return isPlaintextString(data); |
107 | | - case "rle": return isRLEString(data); |
108 | | - } |
109 | | -} |
110 | | - |
111 | | -/** Detect the format of a life string |
112 | | - * |
113 | | - * Note that just because getLifeStringFormat detects a file format does NOT mean that readLifeString will not throw an error |
114 | | - * when called with the given life string. getLifeStringFormat does not confirm if the passed data is valid. |
115 | | - * It only tries to detect the given life string's format by searching for required headers and sequences in the string. |
116 | | - * |
117 | | - * @param data The life string to get the format of |
118 | | - * @returns Either "life 1.06", "life 1.05", "rle", or "plaintext" on the finding |
119 | | - * of a successful format, and an empty string when no format could be found. |
120 | | - */ |
121 | | -export function getLifeStringFormat(data: string): SupportedLifeLikeFormats | "" { |
122 | | - // Note how the tests are ordered. They are ordered from the most simple to identify |
123 | | - // to the least simple to identify. Life 1.06 and Life 1.05 can simply be identified by |
124 | | - // if their file begins with the appropriate header data. isRLEString is identified by the existence of |
125 | | - // a header, although it may not be at the beginning of the file. Finally, Plaintext is identified by simply |
126 | | - // checking if the file parses correctly |
127 | | - |
128 | | - if (isLife106String(data)) { |
129 | | - return "life 1.06" |
130 | | - } else if (isLife105String(data)) { |
131 | | - return "life 1.05" |
132 | | - } else if (isRLEString(data)) { |
133 | | - return "rle" |
134 | | - } else if (isPlaintextString(data)) { |
135 | | - return "plaintext" |
136 | | - } |
137 | | - |
138 | | - return "" |
139 | | -} |
140 | | - |
141 | | -type FileFormatData = ( Life106EncodingData & { format: "life 1.06"} ) | |
142 | | -( PlaintextMatrixWriteData & { format: "plaintext"} ) | |
143 | | -( PlaintextCoordinateWriteData & { format: "plaintext"} ) | |
144 | | -( RLEMatrixEncodingData & { format: "rle" } ) | |
145 | | -( RLECoordinateEncodingData & { format: "rle" }) |
146 | | - |
147 | | -/** |
148 | | - * Write a Life String, keeping the passed data in a portable string format |
149 | | - * |
150 | | - * writeLifeString can write in either one of these formats: |
151 | | - * |
152 | | - * [Life 1.06](https://conwaylife.com/wiki/Life_1.06): |
153 | | - * represented by the presence of { format: "life 1.06" } in the given structured data |
154 | | - * |
155 | | - * [Plaintext](https://conwaylife.com/wiki/Plaintext): |
156 | | - * represented by the presence of { format: "plaintext" } in the given structured data |
157 | | - * |
158 | | - * [Run-Length Encoded (RLE)](https://conwaylife.com/wiki/Run_Length_Encoded): |
159 | | - * represented by the presence of { format: "rle" } in the given structured data |
160 | | - * |
161 | | - * Given all of these formats, rle will likely be the most compressed and desired |
162 | | - * format the large majority of the time. Generally, it is much better to represent |
163 | | - * any semi-large or large pattern, but it is less straight-forward for humans to read |
164 | | - * if that is desired. |
165 | | - * |
166 | | - * Plaintext will be a little larger, but should generally not be used for patterns with a bounding box with a width |
167 | | - * greater than 80 cells. Plaintext, however, could be desired for smaller patterns because of |
168 | | - * the human-readability of the pattern's diagram. |
169 | | - * |
170 | | - * Life 1.06 is also viable for smaller patterns. However, since Life 1.06 lists every single |
171 | | - * coordinate without any compression, Life 1.06 could make for larger files as well. |
172 | | - * |
173 | | - * The particulars of each data format is out of the scope of this little docstring, |
174 | | - * and can be found in DOCUMENTATION.md in the llcacodec repository. This documentation |
175 | | - * could also be found online [here](https://www.github.com/cobyj33/llcacodec/blob/master/DOCUMENTATION.md) |
176 | | - * |
177 | | - * @param data The structured data to use when creating the life string |
178 | | - * @returns A life string containing the passed in compiled data. |
179 | | - */ |
180 | | -export function writeLifeString(data: FileFormatData): string { |
181 | | - switch (data.format) { |
182 | | - case "life 1.06": return writeLife106String(data); |
183 | | - case "plaintext": return writePlaintextString(data); |
184 | | - case "rle": return writeRLEString(data) |
185 | | - } |
186 | | -} |
| 15 | +export { readLifeString, writeLifeString, isLifeStringFormat, getLifeStringFormat } from "./formats/file" |
187 | 16 |
|
188 | 17 | export default { |
189 | 18 | readLifeString, |
|
0 commit comments