Skip to content

Commit

Permalink
DRY-up ALiS parsing and serialization
Browse files Browse the repository at this point in the history
  • Loading branch information
ku1ik committed Jan 28, 2025
1 parent 7e29541 commit 2a33f6d
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 57 deletions.
50 changes: 25 additions & 25 deletions lib/asciinema/streaming/parser/alis_v1.ex
Original file line number Diff line number Diff line change
Expand Up @@ -69,37 +69,22 @@ defmodule Asciinema.Streaming.Parser.AlisV1 do
{time, bytes} = decode_varint(bytes)
{cols, bytes} = decode_varint(bytes)
{rows, bytes} = decode_varint(bytes)

{theme, bytes} =
case bytes do
<<0::8, rest::binary>> ->
{nil, rest}

<<8::8, theme::binary-size((2 + 8) * 3), rest::binary>> ->
{parse_theme(theme), rest}

<<16::8, theme::binary-size((2 + 16) * 3), rest::binary>> ->
{parse_theme(theme), rest}
end

{term_init_len, bytes} = decode_varint(bytes)
<<term_init::binary-size(term_init_len)>> = bytes
{theme, bytes} = parse_theme(bytes)
{term_init, ""} = parse_string(bytes)

%{time: time, term_size: {cols, rows}, term_init: term_init, term_theme: theme}
end

defp parse_output(bytes) do
{time, bytes} = decode_varint(bytes)
{text_len, bytes} = decode_varint(bytes)
<<text::binary-size(text_len)>> = bytes
{text, ""} = parse_string(bytes)

{time, text}
end

defp parse_input(bytes) do
{time, bytes} = decode_varint(bytes)
{text_len, bytes} = decode_varint(bytes)
<<text::binary-size(text_len)>> = bytes
{text, ""} = parse_string(bytes)

{time, text}
end
Expand All @@ -114,8 +99,7 @@ defmodule Asciinema.Streaming.Parser.AlisV1 do

defp parse_marker(bytes) do
{time, bytes} = decode_varint(bytes)
{label_len, bytes} = decode_varint(bytes)
<<label::binary-size(label_len)>> = bytes
{label, ""} = parse_string(bytes)

{time, label}
end
Expand All @@ -126,13 +110,29 @@ defmodule Asciinema.Streaming.Parser.AlisV1 do
time
end

defp decode_varint(bytes) do
{value, rest} = Leb128.decode(bytes)
defp decode_varint(bytes), do: Leb128.decode(bytes)

defp parse_string(bytes) do
{len, bytes} = decode_varint(bytes)
<<text::binary-size(len), rest::binary>> = bytes

{text, rest}
end

defp parse_theme(bytes) do
case bytes do
<<0::8, rest::binary>> ->
{nil, rest}

<<8::8, theme::binary-size((2 + 8) * 3), rest::binary>> ->
{do_parse_theme(theme), rest}

{value, rest}
<<16::8, theme::binary-size((2 + 16) * 3), rest::binary>> ->
{do_parse_theme(theme), rest}
end
end

defp parse_theme(theme) do
defp do_parse_theme(theme) do
colors = for <<r::8, g::8, b::8 <- theme>>, do: {r, g, b}

%{
Expand Down
49 changes: 17 additions & 32 deletions lib/asciinema_web/live_stream_consumer_socket.ex
Original file line number Diff line number Diff line change
Expand Up @@ -204,54 +204,29 @@ defmodule AsciinemaWeb.LiveStreamConsumerSocket do

defp magic_string, do: {:binary, "ALiS\x01"}

defp serialize_init(time, term_size, term_init, nil) do
{cols, rows} = term_size
term_init = term_init || ""
term_init_len = byte_size(term_init)

msg =
<<1::8>> <>
encode_varint(time) <>
encode_varint(cols) <>
encode_varint(rows) <>
<<0::8>> <>
encode_varint(term_init_len) <>
term_init

{:binary, msg}
end

defp serialize_init(time, term_size, term_init, theme) do
{cols, rows} = term_size
theme_format = length(theme.palette)
true = theme_format in [8, 16]
theme = serialize_theme(theme)
term_init = term_init || ""
term_init_len = byte_size(term_init)

msg =
<<1::8>> <>
encode_varint(time) <>
encode_varint(cols) <>
encode_varint(rows) <>
<<theme_format::8>> <>
theme <>
encode_varint(term_init_len) <>
term_init
serialize_theme(theme) <>
serialize_string(term_init)

{:binary, msg}
end

defp serialize_output(time, text) do
text_len = byte_size(text)
msg = <<?o>> <> encode_varint(time) <> encode_varint(text_len) <> text
msg = <<?o>> <> encode_varint(time) <> serialize_string(text)

{:binary, msg}
end

defp serialize_input(time, text) do
text_len = byte_size(text)
msg = <<?i>> <> encode_varint(time) <> encode_varint(text_len) <> text
msg = <<?i>> <> encode_varint(time) <> serialize_string(text)

{:binary, msg}
end
Expand All @@ -264,8 +239,7 @@ defmodule AsciinemaWeb.LiveStreamConsumerSocket do
end

defp serialize_marker(time, label) do
label_len = byte_size(label)
msg = <<?m>> <> encode_varint(time) <> encode_varint(label_len) <> label
msg = <<?m>> <> encode_varint(time) <> serialize_string(label)

{:binary, msg}
end
Expand All @@ -278,7 +252,18 @@ defmodule AsciinemaWeb.LiveStreamConsumerSocket do

defp encode_varint(value), do: Leb128.encode(value)

defp serialize_theme(%{fg: fg, bg: bg, palette: palette}) do
defp serialize_string(text), do: encode_varint(byte_size(text)) <> text

defp serialize_theme(nil), do: <<0::8>>

defp serialize_theme(theme) do
format = length(theme.palette)
true = format in [8, 16]

<<format::8>> <> do_serialize_theme(theme)
end

defp do_serialize_theme(%{fg: fg, bg: bg, palette: palette}) do
for {r, g, b} <- [fg, bg | palette], into: <<>> do
<<r::8, g::8, b::8>>
end
Expand Down

0 comments on commit 2a33f6d

Please sign in to comment.