@@ -19,35 +19,48 @@ package porcupine
1919import cats .Applicative
2020import cats .ContravariantMonoidal
2121import cats .InvariantMonoidal
22- import cats .data .StateT
22+ import cats .data .{ State , StateT }
2323import cats .syntax .all .*
2424import scodec .bits .ByteVector
25-
2625import scala .deriving .Mirror
2726
2827trait Encoder [A ]:
2928 outer =>
3029
30+ def parameters : Int
31+
3132 def encode (a : A ): List [LiteValue ]
3233
33- def either [B ](right : Encoder [B ]): Encoder [Either [A , B ]] = new :
34- def encode (aorb : Either [A , B ]) = aorb match
35- case Left (a) => outer.encode(a)
36- case Right (b) => right.encode(b)
34+ // def either[B](right: Encoder[B]): Encoder[Either[A, B]] = new:
35+ // TODO figure out if this is reasonably implementable
36+ // def parameters: Int = ???
37+ //
38+ // def encode(aorb: Either[A, B]) = aorb match
39+ // case Left(a) => outer.encode(a)
40+ // case Right(b) => right.encode(b)
3741
3842 def opt : Encoder [Option [A ]] =
39- either(Codec .`null`).contramap(_.toLeft(None ))
43+ // either(Codec.`null`).contramap(_.toLeft(None))
44+ new :
45+ def parameters = outer.parameters
46+ def encode (aopt : Option [A ]) = aopt match
47+ case None => Codec .`null`.encode(None )
48+ case Some (a) => outer.encode(a)
4049
4150object Encoder :
4251 given ContravariantMonoidal [Encoder ] = new :
4352 def unit = Codec .unit
4453
4554 def product [A , B ](fa : Encoder [A ], fb : Encoder [B ]) = new :
55+ def parameters =
56+ fa.parameters + fb.parameters
57+
4658 def encode (ab : (A , B )) =
4759 val (a, b) = ab
4860 fa.encode(a) ::: fb.encode(b)
4961
5062 def contramap [A , B ](fa : Encoder [A ])(f : B => A ) = new :
63+ def parameters = fa.parameters
5164 def encode (b : B ) = fa.encode(f(b))
5265
5366trait Decoder [A ]:
@@ -92,52 +105,54 @@ trait Codec[A] extends Encoder[A], Decoder[A]:
92105 def asEncoder : Encoder [A ] = this
93106 def asDecoder : Decoder [A ] = this
94107
95- def either [B ](right : Codec [B ]): Codec [Either [A , B ]] = new :
96- def encode (aorb : Either [A , B ]) =
97- outer.asEncoder.either(right).encode(aorb)
108+ // def either[B](right: Codec[B]): Codec[Either[A, B]] = new:
109+ // def parameters: State[Int, String] =
110+ // outer.asEncoder.either(right).parameters
111+ //
112+ // def encode(aorb: Either[A, B]) =
113+ // outer.asEncoder.either(right).encode(aorb)
114+ //
115+ // def decode = outer.asDecoder.either(right).decode
98116
99- def decode = outer.asDecoder.either(right).decode
100-
101- override def opt : Codec [ Option [A ]] =
102- either( Codec .`null`).imap(_.left.toOption)(_.toLeft( None ))
117+ override def opt : Codec [ Option [ A ]] = new :
118+ def parameters = outer.parameters
119+ def encode ( aopt : Option [A ]) = outer.asEncoder.opt.encode(aopt)
120+ def decode = outer.asDecoder.opt.decode
103121
104122object Codec :
105- val integer : Codec [Long ] = new :
106- def encode (l : Long ) = LiteValue .Integer (l) :: Nil
107- def decode = StateT {
108- case LiteValue .Integer (l) :: tail => Right ((tail, l))
109- case other => Left (new RuntimeException (s " Expected integer, got ${other.headOption}" ))
123+ extension [H ](head : Codec [H ])
124+ def *: [T <: Tuple ](tail : Codec [T ]): Codec [H *: T ] = (head, tail).imapN(_ *: _) { case h *: t => (h, t) }
125+
126+ private final class Simple [T ](
127+ name : String ,
128+ apply : T => LiteValue ,
129+ unapply : PartialFunction [LiteValue , T ]
130+ ) extends Codec [T ] {
131+ override def parameters : Int = 1
132+ override def encode (a : T ): List [LiteValue ] = apply(a) :: Nil
133+ override def decode : StateT [Either [Throwable , * ], List [LiteValue ], T ] = StateT {
134+ case unapply(l) :: tail => Right ((tail, l))
135+ case other => Left (new RuntimeException (s " Expected $name, got ${other.headOption}" ))
110136 }
137+ }
111138
112- val real : Codec [Double ] = new :
113- def encode (d : Double ) = LiteValue .Real (d) :: Nil
114- def decode = StateT {
115- case LiteValue .Real (d) :: tail => Right ((tail, d))
116- case other => Left (new RuntimeException (s " Expected real, got ${other.headOption}" ))
117- }
139+ val integer : Codec [Long ] =
140+ new Simple (" integer" , LiteValue .Integer .apply, { case LiteValue .Integer (i) => i })
118141
119- val text : Codec [String ] = new :
120- def encode (s : String ) = LiteValue .Text (s) :: Nil
121- def decode = StateT {
122- case LiteValue .Text (s) :: tail => Right ((tail, s))
123- case other => Left (new RuntimeException (s " Expected text, got ${other.headOption}" ))
124- }
142+ val real : Codec [Double ] =
143+ new Simple (" real" , LiteValue .Real .apply, { case LiteValue .Real (r) => r })
125144
126- val blob : Codec [ByteVector ] = new :
127- def encode (b : ByteVector ) = LiteValue .Blob (b) :: Nil
128- def decode = StateT {
129- case LiteValue .Blob (b) :: tail => Right ((tail, b))
130- case other => Left (new RuntimeException (s " Expected blob, got ${other.headOption}" ))
131- }
145+ val text : Codec [String ] =
146+ new Simple (" text" , LiteValue .Text .apply, { case LiteValue .Text (t) => t })
132147
133- val `null` : Codec [None .type ] = new :
134- def encode (n : None .type ) = LiteValue .Null :: Nil
135- def decode = StateT {
136- case LiteValue .Null :: tail => Right ((tail, None ))
137- case other => Left (new RuntimeException (s " Expected NULL, got ${other.headOption}" ))
138- }
148+ val blob : Codec [ByteVector ] =
149+ new Simple (" blob" , LiteValue .Blob .apply, { case LiteValue .Blob (b) => b })
150+
151+ val `null` : Codec [None .type ] =
152+ new Simple (" NULL" , _ => LiteValue .Null , { case LiteValue .Null => None })
139153
140154 def unit : Codec [Unit ] = new :
155+ def parameters : Int = 0
141156 def encode (u : Unit ) = Nil
142157 def decode = StateT .pure(())
143158
@@ -147,12 +162,16 @@ object Codec:
147162 def unit = Codec .unit
148163
149164 def product [A , B ](fa : Codec [A ], fb : Codec [B ]) = new :
165+ def parameters =
166+ fa.parameters + fb.parameters
167+
150168 def encode (ab : (A , B )) =
151169 val (a, b) = ab
152170 fa.encode(a) ::: fb.encode(b)
153171
154172 def decode = fa.decode.product(fb.decode)
155173
156174 def imap [A , B ](fa : Codec [A ])(f : A => B )(g : B => A ) = new :
175+ def parameters = fa.parameters
157176 def encode (b : B ) = fa.encode(g(b))
158177 def decode = fa.decode.map(f)
0 commit comments