]> gitweb.factorcode.org Git - factor.git/commitdiff
yenc: adding yEnc format encoding/decoding
authorJohn Benediktsson <mrjbq7@gmail.com>
Sun, 30 Jan 2022 18:24:49 +0000 (10:24 -0800)
committerJohn Benediktsson <mrjbq7@gmail.com>
Sun, 30 Jan 2022 18:24:49 +0000 (10:24 -0800)
extra/yenc/authors.txt [new file with mode: 0644]
extra/yenc/summary.txt [new file with mode: 0644]
extra/yenc/yenc-tests.factor [new file with mode: 0644]
extra/yenc/yenc.factor [new file with mode: 0644]

diff --git a/extra/yenc/authors.txt b/extra/yenc/authors.txt
new file mode 100644 (file)
index 0000000..e091bb8
--- /dev/null
@@ -0,0 +1 @@
+John Benediktsson
diff --git a/extra/yenc/summary.txt b/extra/yenc/summary.txt
new file mode 100644 (file)
index 0000000..e9ce82a
--- /dev/null
@@ -0,0 +1 @@
+Encoding and decoding of the yEnc format
diff --git a/extra/yenc/yenc-tests.factor b/extra/yenc/yenc-tests.factor
new file mode 100644 (file)
index 0000000..982fe8c
--- /dev/null
@@ -0,0 +1,9 @@
+USING: byte-arrays io.encodings.binary io.files kernel sequences
+tools.test yenc ;
+
+{ t } [ 255 <iota> >byte-array dup yenc ydec = ] unit-test
+
+{ t } [
+    "resource:LICENSE.txt"
+    [ yenc-file ydec-file 2nip ] [ binary file-contents ] bi =
+] unit-test
diff --git a/extra/yenc/yenc.factor b/extra/yenc/yenc.factor
new file mode 100644 (file)
index 0000000..ed85ea6
--- /dev/null
@@ -0,0 +1,85 @@
+! Copyright (C) 2022 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license
+
+USING: accessors assocs checksums checksums.crc32 combinators
+endian formatting io.encodings.binary io.files io.files.info
+kernel make math math.functions math.order namespaces sequences
+splitting strings ;
+
+IN: yenc
+
+! TODO: Support yparts
+
+SYMBOL: yenc-line-length
+yenc-line-length [ 128 ] initialize
+
+<PRIVATE
+
+: yenc-line% ( -- )
+    building get length yenc-line-length get
+    [ 2 + ] bi@ divisor? [ "\r\n" % ] when ;
+
+: yenc% ( bytes -- )
+    [
+        42 + 256 mod
+        dup "\0\r\n=" member? [ CHAR: = , 64 + 256 mod ] when ,
+        yenc-line%
+    ] each ;
+
+PRIVATE>
+
+: yenc ( bytes -- yenc )
+    [ yenc% ] B{ } make ;
+
+<PRIVATE
+
+: ybegin% ( path -- )
+    [ file-info size>> yenc-line-length get ] keep
+    "=ybegin size=%d line=%d name=%s\n" sprintf % ;
+
+: yend% ( path -- )
+    [ file-info size>> ] [ crc32 checksum-bytes be> ] bi
+    "\n=yend size=%d crc32=%08X" sprintf % ;
+
+PRIVATE>
+
+: yenc-file ( path -- yenc )
+    [
+        [ ybegin% ]
+        [ binary file-contents yenc% ]
+        [ yend% ] tri
+    ] B{ } make ;
+
+<PRIVATE
+
+: ydec, ( encode? ch -- encode?' )
+    dup "\r\n" member? [ drop ] [
+        2dup [ not ] [ CHAR: = = ] bi* and [ 2drop t ] [
+            over [ 64 - [ drop f ] dip ] when
+            dup 0 41 between? [ 214 + ] [ 42 - ] if ,
+        ] if
+    ] if ;
+
+PRIVATE>
+
+: ydec ( yenc -- bytes )
+    [ f swap [ ydec, ] each drop ] B{ } make ;
+
+<PRIVATE
+
+: parse-metadata ( line -- metadata )
+    >string " " split [ "=" split1 ] H{ } map>assoc ;
+
+: find-metadata ( lines type -- metadata i )
+   [ '[ _ head? ] find ] keep ?head drop parse-metadata swap ;
+
+PRIVATE>
+
+: ydec-file ( yenc -- ybegin yend bytes )
+    "\n" split {
+        [ "=ybegin " find-metadata 1 + ]
+        [ "=yend " find-metadata swapd ]
+        [ <slice> ]
+    } cleave [
+        f swap [ [ ydec, ] each ] each drop
+    ] B{ } make ;