/
payload.ex
129 lines (106 loc) · 3.21 KB
/
payload.ex
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
defprotocol Membrane.Payload do
@moduledoc """
This protocol describes actions common to all payload types.
The most basic payload type is simply a binary for which `#{__MODULE__}`
is implemented by the Membrane Core.
"""
defmodule Behaviour do
@moduledoc """
Behaviour that should be implemented by every module that has
`Membrane.Payload` protocol implementation.
"""
@doc """
Creates an empty payload
"""
@callback empty() :: Membrane.Payload.t()
@doc """
Creates a new payload initialized with the given binary
"""
@callback new(binary()) :: Membrane.Payload.t()
end
@typedoc """
A type describing all the types that implement `Membrane.Payload` protocol.
"""
@type t :: any()
@doc """
Returns total size of payload in bytes
"""
@spec size(payload :: t()) :: non_neg_integer()
def size(payload)
@doc """
Splits the payload at given position (1st part has the size equal to `at_pos` argument)
`at_pos` has to be greater than 0 and smaller than the size of payload, otherwise
an error is raised. This guarantees returned payloads are never empty.
"""
@spec split_at(payload :: t(), at_pos :: pos_integer()) :: {t(), t()}
def split_at(payload, at_pos)
@doc """
Concatenates the contents of two payloads.
"""
@spec concat(left :: t(), right :: t()) :: t()
def concat(left, right)
@doc """
Drops first `n` bytes of payload.
"""
@spec drop(payload :: t(), n :: non_neg_integer()) :: t()
def drop(payload, n)
@doc """
Converts payload into binary
"""
@spec to_binary(t()) :: binary()
def to_binary(payload)
@doc """
Returns a module responsible for this type of payload
and implementing `Membrane.Payload.Behaviour`
"""
@spec module(t()) :: module()
def module(payload)
end
defmodule Membrane.Payload.Binary do
@moduledoc """
`Membrane.Payload.Behaviour` implementation for binary payload.
Complements `Membrane.Payload` protocol implementation.
"""
@behaviour Membrane.Payload.Behaviour
@impl true
def empty(), do: <<>>
@impl true
def new(data) when is_binary(data) do
data
end
end
defimpl Membrane.Payload, for: BitString do
alias Membrane.Payload
@compile {:inline, module: 1}
@impl true
@spec size(payload :: binary()) :: pos_integer
def size(payload) when is_binary(payload) do
payload |> byte_size()
end
@impl true
@spec split_at(binary(), pos_integer) :: {binary(), binary()}
def split_at(payload, at_pos)
when is_binary(payload) and 0 < at_pos and at_pos < byte_size(payload) do
<<part1::binary-size(at_pos), part2::binary>> = payload
{part1, part2}
end
@impl true
@spec concat(left :: binary(), right :: binary()) :: binary()
def concat(left, right) when is_binary(left) and is_binary(right) do
left <> right
end
@impl true
@spec drop(payload :: binary(), bytes :: non_neg_integer()) :: binary()
def drop(payload, bytes) when is_binary(payload) do
<<_dropped::binary-size(bytes), rest::binary>> = payload
rest
end
@impl true
@spec to_binary(binary()) :: binary()
def to_binary(payload) when is_binary(payload) do
payload
end
@impl true
@spec module(binary()) :: module()
def module(_payload), do: Payload.Binary
end