Input.scala 27.6 KB
Newer Older
D
Dejan Mijić 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
 * Copyright 2021 John A. De Goes and the ZIO contributors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

D
Dejan Mijić 已提交
17 18
package zio.redis

梦境迷离's avatar
梦境迷离 已提交
19
import zio._
20
import zio.redis.internal.{RespCommand, RespCommandArgument, Utf8Codec}
A
Anatoly Sergeev 已提交
21
import zio.schema.codec.BinaryCodec
D
Dejan Mijić 已提交
22

D
Dejan Mijić 已提交
23 24 25
import java.time.Instant
import java.util.concurrent.TimeUnit

26
sealed trait Input[-A] { self =>
27
  private[redis] def encode(data: A): RespCommand
28

29 30 31 32
  final def contramap[B](f: B => A): Input[B] =
    new Input[B] {
      def encode(data: B): RespCommand = self.encode(f(data))
    }
D
Dejan Mijić 已提交
33
}
D
Dejan Mijić 已提交
34 35

object Input {
36 37
  def apply[A](implicit input: Input[A]): Input[A] = input

D
Dejan Mijić 已提交
38
  case object AbsTtlInput extends Input[AbsTtl] {
39
    def encode(data: AbsTtl): RespCommand =
40
      RespCommand(RespCommandArgument.Literal(data.asString))
D
Dejan Mijić 已提交
41 42
  }

43
  case object AddressInput extends Input[Address] {
44
    def encode(data: Address): RespCommand =
45
      RespCommand(RespCommandArgument.Unknown(data.asString))
46 47
  }

D
Dejan Mijić 已提交
48
  case object AggregateInput extends Input[Aggregate] {
49
    def encode(data: Aggregate): RespCommand =
50
      RespCommand(RespCommandArgument.Literal("AGGREGATE"), RespCommandArgument.Literal(data.asString))
D
Dejan Mijić 已提交
51 52
  }

53
  case object AlphaInput extends Input[Alpha] {
54
    def encode(data: Alpha): RespCommand =
55
      RespCommand(RespCommandArgument.Literal(data.asString))
56 57
  }

D
Dejan Mijić 已提交
58
  case object AuthInput extends Input[Auth] {
59
    import Utf8Codec.codec
60 61

    def encode(data: Auth): RespCommand =
62
      data.username match {
63 64 65
        case Some(username) =>
          RespCommand(RespCommandArgument.Value(username), RespCommandArgument.Value(data.password))
        case None => RespCommand(RespCommandArgument.Value(data.password))
66 67
      }

D
Dejan Mijić 已提交
68 69 70
  }

  case object BoolInput extends Input[Boolean] {
71
    def encode(data: Boolean): RespCommand =
72
      RespCommand(RespCommandArgument.Literal(if (data) "1" else "0"))
B
barthorre 已提交
73 74 75
  }

  case object StralgoLcsQueryTypeInput extends Input[StrAlgoLcsQueryType] {
76
    def encode(data: StrAlgoLcsQueryType): RespCommand = data match {
77
      case StrAlgoLcsQueryType.Len => RespCommand(RespCommandArgument.Literal("LEN"))
B
barthorre 已提交
78
      case StrAlgoLcsQueryType.Idx(minMatchLength, withMatchLength) => {
79
        val idx = Chunk.single(RespCommandArgument.Literal("IDX"))
B
barthorre 已提交
80
        val min =
81
          if (minMatchLength > 1)
82 83
            Chunk(RespCommandArgument.Literal("MINMATCHLEN"), RespCommandArgument.Unknown(minMatchLength.toString))
          else Chunk.empty[RespCommandArgument]
84
        val length =
85 86
          if (withMatchLength) Chunk.single(RespCommandArgument.Literal("WITHMATCHLEN"))
          else Chunk.empty[RespCommandArgument]
87
        RespCommand(Chunk(idx, min, length).flatten)
B
barthorre 已提交
88 89 90 91
      }
    }
  }

92
  case object BitFieldCommandInput extends Input[BitFieldCommand] {
93
    def encode(data: BitFieldCommand): RespCommand = {
94 95
      import BitFieldCommand._

96 97
      val respArgs = data match {
        case BitFieldGet(t, o) =>
98 99 100 101 102
          Chunk(
            RespCommandArgument.Literal("GET"),
            RespCommandArgument.Unknown(t.asString),
            RespCommandArgument.Unknown(o.toString)
          )
D
Dejan Mijić 已提交
103
        case BitFieldSet(t, o, v) =>
104
          Chunk(
105 106 107 108
            RespCommandArgument.Literal("SET"),
            RespCommandArgument.Unknown(t.asString),
            RespCommandArgument.Unknown(o.toString),
            RespCommandArgument.Unknown(v.toString)
109
          )
110
        case BitFieldIncr(t, o, i) =>
111
          Chunk(
112 113 114 115
            RespCommandArgument.Literal("INCRBY"),
            RespCommandArgument.Unknown(t.asString),
            RespCommandArgument.Unknown(o.toString),
            RespCommandArgument.Unknown(i.toString)
116
          )
117 118
        case bfo: BitFieldOverflow =>
          Chunk(RespCommandArgument.Literal("OVERFLOW"), RespCommandArgument.Literal(bfo.asString))
119
      }
120
      RespCommand(respArgs)
121
    }
D
Dejan Mijić 已提交
122 123 124
  }

  case object BitOperationInput extends Input[BitOperation] {
125
    def encode(data: BitOperation): RespCommand =
126
      RespCommand(RespCommandArgument.Literal(data.asString))
D
Dejan Mijić 已提交
127 128 129
  }

  case object BitPosRangeInput extends Input[BitPosRange] {
130
    def encode(data: BitPosRange): RespCommand = {
131 132
      val start    = RespCommandArgument.Unknown(data.start.toString)
      val respArgs = data.end.fold(Chunk.single(start))(end => Chunk(start, RespCommandArgument.Unknown(end.toString)))
133
      RespCommand(respArgs)
D
Dejan Mijić 已提交
134 135 136
    }
  }

137
  case object ByInput extends Input[String] {
138
    def encode(data: String): RespCommand =
139
      RespCommand(RespCommandArgument.Literal("BY"), RespCommandArgument.Unknown(data))
140 141
  }

D
Dejan Mijić 已提交
142
  case object ChangedInput extends Input[Changed] {
143
    def encode(data: Changed): RespCommand =
144
      RespCommand(RespCommandArgument.Literal(data.asString))
D
Dejan Mijić 已提交
145 146
  }

147
  case object ClientKillInput extends Input[ClientKillFilter] {
148
    def encode(data: ClientKillFilter): RespCommand = data match {
149
      case addr: ClientKillFilter.Address =>
150
        RespCommand(RespCommandArgument.Literal("ADDR"), RespCommandArgument.Unknown(addr.asString))
151
      case laddr: ClientKillFilter.LocalAddress =>
152
        RespCommand(RespCommandArgument.Literal("LADDR"), RespCommandArgument.Unknown(laddr.asString))
153
      case ClientKillFilter.Id(clientId) =>
154
        RespCommand(RespCommandArgument.Literal("ID"), RespCommandArgument.Unknown(clientId.toString))
155
      case ClientKillFilter.Type(clientType) =>
156 157 158
        RespCommand(RespCommandArgument.Literal("TYPE"), RespCommandArgument.Literal(clientType.asString))
      case ClientKillFilter.User(username) =>
        RespCommand(RespCommandArgument.Literal("USER"), RespCommandArgument.Unknown(username))
159
      case ClientKillFilter.SkipMe(skip) =>
160
        RespCommand(RespCommandArgument.Literal("SKIPME"), RespCommandArgument.Literal(if (skip) "YES" else "NO"))
161 162 163
    }
  }

164 165 166 167 168
  case object ClientTypeInput extends Input[ClientType] {
    def encode(data: ClientType): RespCommand =
      RespCommand(RespCommandArgument.Literal("TYPE"), RespCommandArgument.Literal(data.asString))
  }

169
  case object ClientPauseModeInput extends Input[ClientPauseMode] {
170
    def encode(data: ClientPauseMode): RespCommand =
171
      RespCommand(RespCommandArgument.Literal(data.asString))
172 173 174 175 176 177
  }

  case object ClientTrackingInput
      extends Input[Option[(Option[Long], Option[ClientTrackingMode], Boolean, Chunk[String])]] {
    def encode(
      data: Option[(Option[Long], Option[ClientTrackingMode], Boolean, Chunk[String])]
178
    ): RespCommand =
179 180 181
      data match {
        case Some((clientRedir, mode, noLoop, prefixes)) =>
          val modeChunk = mode match {
182 183 184
            case Some(ClientTrackingMode.OptIn)     => RespCommand(RespCommandArgument.Literal("OPTIN"))
            case Some(ClientTrackingMode.OptOut)    => RespCommand(RespCommandArgument.Literal("OPTOUT"))
            case Some(ClientTrackingMode.Broadcast) => RespCommand(RespCommandArgument.Literal("BCAST"))
185
            case None                               => RespCommand.empty
186
          }
187 188
          val loopChunk = if (noLoop) RespCommand(RespCommandArgument.Literal("NOLOOP")) else RespCommand.empty
          RespCommand(RespCommandArgument.Literal("ON")) ++
189
            clientRedir.fold(RespCommand.empty)(id =>
190
              RespCommand(RespCommandArgument.Literal("REDIRECT"), RespCommandArgument.Unknown(id.toString))
191 192
            ) ++
            RespCommand(
193 194 195
              prefixes.flatMap(prefix =>
                Chunk(RespCommandArgument.Literal("PREFIX"), RespCommandArgument.Unknown(prefix))
              )
196 197 198 199
            ) ++
            modeChunk ++
            loopChunk
        case None =>
200
          RespCommand(RespCommandArgument.Literal("OFF"))
201 202 203
      }
  }

D
Dejan Mijić 已提交
204
  case object CopyInput extends Input[Copy] {
205
    def encode(data: Copy): RespCommand =
206
      RespCommand(RespCommandArgument.Literal(data.asString))
D
Dejan Mijić 已提交
207 208 209
  }

  case object CountInput extends Input[Count] {
210
    def encode(data: Count): RespCommand =
211
      RespCommand(RespCommandArgument.Literal("COUNT"), RespCommandArgument.Unknown(data.count.toString))
D
Dejan Mijić 已提交
212 213
  }

214
  case object RedisTypeInput extends Input[RedisType] {
215
    def encode(data: RedisType): RespCommand =
216
      RespCommand(RespCommandArgument.Literal("TYPE"), RespCommandArgument.Literal(data.asString))
217 218 219
  }

  case object PatternInput extends Input[Pattern] {
220
    def encode(data: Pattern): RespCommand =
221
      RespCommand(RespCommandArgument.Literal("MATCH"), RespCommandArgument.Unknown(data.pattern))
222 223
  }

224
  case object GetInput extends Input[String] {
225
    def encode(data: String): RespCommand =
226
      RespCommand(RespCommandArgument.Literal("GET"), RespCommandArgument.Unknown(data))
227 228
  }

229
  case object PositionInput extends Input[Position] {
230
    def encode(data: Position): RespCommand =
231
      RespCommand(RespCommandArgument.Literal(data.asString))
232 233
  }

234
  case object SideInput extends Input[Side] {
235
    def encode(data: Side): RespCommand =
236
      RespCommand(RespCommandArgument.Literal(data.asString))
237 238
  }

D
Dejan Mijić 已提交
239
  case object DoubleInput extends Input[Double] {
240
    def encode(data: Double): RespCommand =
241
      RespCommand(RespCommandArgument.Unknown(data.toString))
D
Dejan Mijić 已提交
242 243 244
  }

  case object DurationMillisecondsInput extends Input[Duration] {
245
    def encode(data: Duration): RespCommand =
246
      RespCommand(RespCommandArgument.Unknown(data.toMillis.toString))
D
Dejan Mijić 已提交
247 248 249
  }

  case object DurationSecondsInput extends Input[Duration] {
250
    def encode(data: Duration): RespCommand = {
D
Dejan Mijić 已提交
251
      val seconds = TimeUnit.MILLISECONDS.toSeconds(data.toMillis)
252
      RespCommand(RespCommandArgument.Unknown(seconds.toString))
D
Dejan Mijić 已提交
253 254 255
    }
  }

256
  case object DurationTtlInput extends Input[Duration] {
257
    def encode(data: Duration): RespCommand = {
A
Aleksandar Novaković 已提交
258
      val milliseconds = data.toMillis
259
      RespCommand(RespCommandArgument.Literal("PX"), RespCommandArgument.Unknown(milliseconds.toString))
A
Aleksandar Novaković 已提交
260 261 262
    }
  }

D
Dejan Mijić 已提交
263
  case object FreqInput extends Input[Freq] {
264
    def encode(data: Freq): RespCommand =
265
      RespCommand(RespCommandArgument.Literal("FREQ"), RespCommandArgument.Unknown(data.frequency))
D
Dejan Mijić 已提交
266 267
  }

268 269 270 271 272
  case object GetKeywordInput extends Input[GetKeyword] {
    def encode(data: GetKeyword): RespCommand =
      RespCommand(RespCommandArgument.Literal(data.asString))
  }

D
Dejan Mijić 已提交
273
  case object IdleTimeInput extends Input[IdleTime] {
274
    def encode(data: IdleTime): RespCommand =
275
      RespCommand(RespCommandArgument.Literal("IDLETIME"), RespCommandArgument.Unknown(data.seconds.toString))
D
Dejan Mijić 已提交
276 277 278
  }

  case object IncrementInput extends Input[Increment] {
279
    def encode(data: Increment): RespCommand =
280
      RespCommand(RespCommandArgument.Literal(data.asString))
D
Dejan Mijić 已提交
281 282 283
  }

  case object KeepTtlInput extends Input[KeepTtl] {
284
    def encode(data: KeepTtl): RespCommand =
285
      RespCommand(RespCommandArgument.Literal(data.asString))
D
Dejan Mijić 已提交
286 287 288
  }

  case object LimitInput extends Input[Limit] {
289
    def encode(data: Limit): RespCommand =
290
      RespCommand(
291 292 293
        RespCommandArgument.Literal("LIMIT"),
        RespCommandArgument.Unknown(data.offset.toString),
        RespCommandArgument.Unknown(data.count.toString)
294
      )
D
Dejan Mijić 已提交
295 296 297
  }

  case object LongInput extends Input[Long] {
298
    def encode(data: Long): RespCommand =
299
      RespCommand(RespCommandArgument.Unknown(data.toString))
D
Dejan Mijić 已提交
300 301 302
  }

  case object LongLatInput extends Input[LongLat] {
303
    def encode(data: LongLat): RespCommand =
304 305 306 307
      RespCommand(
        RespCommandArgument.Unknown(data.longitude.toString),
        RespCommandArgument.Unknown(data.latitude.toString)
      )
D
Dejan Mijić 已提交
308 309
  }

310 311
  final case class MemberScoreInput[M: BinaryCodec]() extends Input[MemberScore[M]] {
    def encode(data: MemberScore[M]): RespCommand =
312
      RespCommand(RespCommandArgument.Unknown(data.score.toString), RespCommandArgument.Value(data.member))
D
Dejan Mijić 已提交
313 314 315
  }

  case object NoInput extends Input[Unit] {
316
    def encode(data: Unit): RespCommand = RespCommand.empty
D
Dejan Mijić 已提交
317 318 319
  }

  final case class NonEmptyList[-A](input: Input[A]) extends Input[(A, List[A])] {
320
    def encode(data: (A, List[A])): RespCommand =
321
      (data._1 :: data._2).foldLeft(RespCommand.empty)((acc, a) => acc ++ input.encode(a))
D
Dejan Mijić 已提交
322 323 324
  }

  case object OrderInput extends Input[Order] {
325
    def encode(data: Order): RespCommand =
326
      RespCommand(RespCommandArgument.Unknown(data.asString))
D
Dejan Mijić 已提交
327 328 329
  }

  case object RadiusUnitInput extends Input[RadiusUnit] {
330
    def encode(data: RadiusUnit): RespCommand =
331
      RespCommand(RespCommandArgument.Unknown(data.asString))
D
Dejan Mijić 已提交
332 333 334
  }

  case object RangeInput extends Input[Range] {
335
    def encode(data: Range): RespCommand =
336
      RespCommand(RespCommandArgument.Unknown(data.start.toString), RespCommandArgument.Unknown(data.end.toString))
D
Dejan Mijić 已提交
337 338 339
  }

  case object ReplaceInput extends Input[Replace] {
340
    def encode(data: Replace): RespCommand =
341
      RespCommand(RespCommandArgument.Literal(data.asString))
D
Dejan Mijić 已提交
342 343 344
  }

  case object StoreDistInput extends Input[StoreDist] {
345
    def encode(data: StoreDist): RespCommand =
346
      RespCommand(RespCommandArgument.Literal("STOREDIST"), RespCommandArgument.Unknown(data.key))
D
Dejan Mijić 已提交
347 348 349
  }

  case object StoreInput extends Input[Store] {
350
    def encode(data: Store): RespCommand =
351
      RespCommand(RespCommandArgument.Literal("STORE"), RespCommandArgument.Unknown(data.key))
D
Dejan Mijić 已提交
352 353
  }

A
Anatoly Sergeev 已提交
354
  case object StringInput extends Input[String] {
355
    def encode(data: String): RespCommand =
356
      RespCommand(RespCommandArgument.Unknown(data))
357 358 359
  }

  case object CommandNameInput extends Input[String] {
360
    def encode(data: String): RespCommand =
361
      RespCommand(RespCommandArgument.CommandName(data))
D
Dejan Mijić 已提交
362 363
  }

364 365
  final case class ArbitraryValueInput[A: BinaryCodec]() extends Input[A] {
    def encode(data: A): RespCommand =
366
      RespCommand(RespCommandArgument.Value(data))
D
Dejan Mijić 已提交
367 368
  }

369 370
  final case class ArbitraryKeyInput[A: BinaryCodec]() extends Input[A] {
    def encode(data: A): RespCommand =
371
      RespCommand(RespCommandArgument.Key(data))
372 373 374
  }

  case object ValueInput extends Input[Chunk[Byte]] {
375
    def encode(data: Chunk[Byte]): RespCommand =
376
      RespCommand(RespCommandArgument.Value(data))
377 378
  }

D
Dejan Mijić 已提交
379
  final case class OptionalInput[-A](a: Input[A]) extends Input[Option[A]] {
380
    def encode(data: Option[A]): RespCommand =
381
      data.fold(RespCommand.empty)(a.encode)
D
Dejan Mijić 已提交
382 383 384
  }

  case object TimeSecondsInput extends Input[Instant] {
385
    def encode(data: Instant): RespCommand =
386
      RespCommand(RespCommandArgument.Unknown(data.getEpochSecond.toString))
D
Dejan Mijić 已提交
387 388 389
  }

  case object TimeMillisecondsInput extends Input[Instant] {
390
    def encode(data: Instant): RespCommand =
391
      RespCommand(RespCommandArgument.Unknown(data.toEpochMilli.toString))
D
Dejan Mijić 已提交
392 393
  }

D
Dejan Mijić 已提交
394
  case object WeightsInput extends Input[::[Double]] {
395
    def encode(data: ::[Double]): RespCommand = {
396 397
      val args = data.foldLeft(Chunk.single[RespCommandArgument](RespCommandArgument.Literal("WEIGHTS"))) { (acc, a) =>
        acc ++ Chunk.single(RespCommandArgument.Unknown(a.toString))
398 399 400
      }
      RespCommand(args)
    }
M
Maciej Bąk 已提交
401 402
  }

403
  case object IdleInput extends Input[Duration] {
404
    def encode(data: Duration): RespCommand =
405
      RespCommand(RespCommandArgument.Literal("IDLE"), RespCommandArgument.Unknown(data.toMillis.toString))
406 407 408
  }

  case object TimeInput extends Input[Duration] {
409
    def encode(data: Duration): RespCommand =
410
      RespCommand(RespCommandArgument.Literal("TIME"), RespCommandArgument.Unknown(data.toMillis.toString))
411 412 413
  }

  case object RetryCountInput extends Input[Long] {
414
    def encode(data: Long): RespCommand =
415
      RespCommand(RespCommandArgument.Literal("RETRYCOUNT"), RespCommandArgument.Unknown(data.toString))
416 417
  }

418 419 420
  final case class XGroupCreateInput[K: BinaryCodec, G: BinaryCodec, I: BinaryCodec]()
      extends Input[XGroupCommand.Create[K, G, I]] {
    def encode(data: XGroupCommand.Create[K, G, I]): RespCommand = {
421
      val chunk = Chunk(
422 423 424 425
        RespCommandArgument.Literal("CREATE"),
        RespCommandArgument.Key(data.key),
        RespCommandArgument.Unknown(data.group),
        RespCommandArgument.Unknown(data.id)
426
      )
427

428
      RespCommand(if (data.mkStream) chunk :+ RespCommandArgument.Literal(MkStream.asString) else chunk)
A
Anatoly Sergeev 已提交
429
    }
430 431
  }

432 433 434
  final case class XGroupSetIdInput[K: BinaryCodec, G: BinaryCodec, I: BinaryCodec]()
      extends Input[XGroupCommand.SetId[K, G, I]] {
    def encode(data: XGroupCommand.SetId[K, G, I]): RespCommand =
435
      RespCommand(
436 437 438 439
        RespCommandArgument.Literal("SETID"),
        RespCommandArgument.Key(data.key),
        RespCommandArgument.Unknown(data.group),
        RespCommandArgument.Unknown(data.id)
440
      )
441 442
  }

443 444
  final case class XGroupDestroyInput[K: BinaryCodec, G: BinaryCodec]() extends Input[XGroupCommand.Destroy[K, G]] {
    def encode(data: XGroupCommand.Destroy[K, G]): RespCommand =
445 446 447 448 449
      RespCommand(
        RespCommandArgument.Literal("DESTROY"),
        RespCommandArgument.Key(data.key),
        RespCommandArgument.Unknown(data.group)
      )
450 451
  }

452
  final case class XGroupCreateConsumerInput[K: BinaryCodec, G: BinaryCodec, C: BinaryCodec]()
A
Anatoly Sergeev 已提交
453
      extends Input[XGroupCommand.CreateConsumer[K, G, C]] {
454
    def encode(data: XGroupCommand.CreateConsumer[K, G, C]): RespCommand =
455
      RespCommand(
456 457 458 459
        RespCommandArgument.Literal("CREATECONSUMER"),
        RespCommandArgument.Key(data.key),
        RespCommandArgument.Unknown(data.group),
        RespCommandArgument.Unknown(data.consumer)
460
      )
461 462
  }

463
  final case class XGroupDelConsumerInput[K: BinaryCodec, G: BinaryCodec, C: BinaryCodec]()
A
Anatoly Sergeev 已提交
464
      extends Input[XGroupCommand.DelConsumer[K, G, C]] {
465
    def encode(data: XGroupCommand.DelConsumer[K, G, C]): RespCommand =
466
      RespCommand(
467 468 469 470
        RespCommandArgument.Literal("DELCONSUMER"),
        RespCommandArgument.Key(data.key),
        RespCommandArgument.Unknown(data.group),
        RespCommandArgument.Unknown(data.consumer)
471
      )
472 473
  }

474
  case object BlockInput extends Input[Duration] {
475
    def encode(data: Duration): RespCommand =
476
      RespCommand(RespCommandArgument.Literal("BLOCK"), RespCommandArgument.Unknown(data.toMillis.toString))
477 478
  }

479 480
  final case class StreamsInput[K: BinaryCodec, V: BinaryCodec]() extends Input[((K, V), Chunk[(K, V)])] {
    def encode(data: ((K, V), Chunk[(K, V)])): RespCommand = {
A
Anatoly Sergeev 已提交
481
      val (keys, ids) = (data._1 +: data._2).map { case (key, value) =>
482
        (RespCommandArgument.Key(key), RespCommandArgument.Value(value))
A
Anatoly Sergeev 已提交
483
      }.unzip
484

485
      RespCommand(Chunk.single(RespCommandArgument.Literal("STREAMS")) ++ keys ++ ids)
486 487 488 489
    }
  }

  case object NoAckInput extends Input[NoAck] {
490
    def encode(data: NoAck): RespCommand =
491
      RespCommand(RespCommandArgument.Unknown(data.asString))
492 493
  }

H
Hans Christian Wilhelm 已提交
494
  case object StreamMaxLenInput extends Input[StreamMaxLen] {
495
    def encode(data: StreamMaxLen): RespCommand = {
496
      val chunk =
497 498
        if (data.approximate) Chunk(RespCommandArgument.Literal("MAXLEN"), RespCommandArgument.Literal("~"))
        else Chunk.single(RespCommandArgument.Literal("MAXLEN"))
499

500
      RespCommand(chunk :+ RespCommandArgument.Unknown(data.count.toString))
501 502 503
    }
  }

H
Hans Christian Wilhelm 已提交
504
  case object ListMaxLenInput extends Input[ListMaxLen] {
505
    def encode(data: ListMaxLen): RespCommand =
506
      RespCommand(RespCommandArgument.Literal("MAXLEN"), RespCommandArgument.Unknown(data.count.toString))
H
Hans Christian Wilhelm 已提交
507 508 509
  }

  case object RankInput extends Input[Rank] {
510
    def encode(data: Rank): RespCommand =
511
      RespCommand(RespCommandArgument.Literal("RANK"), RespCommandArgument.Unknown(data.rank.toString))
H
Hans Christian Wilhelm 已提交
512 513
  }

D
Dejan Mijić 已提交
514
  final case class Tuple2[-A, -B](_1: Input[A], _2: Input[B]) extends Input[(A, B)] {
515
    def encode(data: (A, B)): RespCommand =
A
Anatoly Sergeev 已提交
516
      _1.encode(data._1) ++ _2.encode(data._2)
D
Dejan Mijić 已提交
517 518 519
  }

  final case class Tuple3[-A, -B, -C](_1: Input[A], _2: Input[B], _3: Input[C]) extends Input[(A, B, C)] {
520
    def encode(data: (A, B, C)): RespCommand =
521
      _1.encode(data._1) ++ _2.encode(data._2) ++ _3.encode(data._3)
D
Dejan Mijić 已提交
522
  }
D
Dejan Mijić 已提交
523 524

  final case class Tuple4[-A, -B, -C, -D](_1: Input[A], _2: Input[B], _3: Input[C], _4: Input[D])
D
Dejan Mijić 已提交
525
      extends Input[(A, B, C, D)] {
526
    def encode(data: (A, B, C, D)): RespCommand =
D
Dejan Mijić 已提交
527 528
      _1.encode(data._1) ++ _2.encode(data._2) ++ _3.encode(data._3) ++ _4.encode(data._4)
  }
D
Dejan Mijić 已提交
529 530

  final case class Tuple5[-A, -B, -C, -D, -E](_1: Input[A], _2: Input[B], _3: Input[C], _4: Input[D], _5: Input[E])
D
Dejan Mijić 已提交
531
      extends Input[(A, B, C, D, E)] {
532
    def encode(data: (A, B, C, D, E)): RespCommand =
D
Dejan Mijić 已提交
533 534
      _1.encode(data._1) ++ _2.encode(data._2) ++ _3.encode(data._3) ++ _4.encode(data._4) ++ _5.encode(data._5)
  }
D
Dejan Mijić 已提交
535

536 537 538 539 540 541 542 543
  final case class Tuple6[-A, -B, -C, -D, -E, -F](
    _1: Input[A],
    _2: Input[B],
    _3: Input[C],
    _4: Input[D],
    _5: Input[E],
    _6: Input[F]
  ) extends Input[(A, B, C, D, E, F)] {
544
    def encode(data: (A, B, C, D, E, F)): RespCommand =
545 546 547 548
      _1.encode(data._1) ++ _2.encode(data._2) ++ _3.encode(data._3) ++ _4.encode(data._4) ++ _5.encode(data._5) ++
        _6.encode(data._6)
  }

549 550 551 552 553 554 555 556
  final case class Tuple7[-A, -B, -C, -D, -E, -F, -G](
    _1: Input[A],
    _2: Input[B],
    _3: Input[C],
    _4: Input[D],
    _5: Input[E],
    _6: Input[F],
    _7: Input[G]
D
Dejan Mijić 已提交
557
  ) extends Input[(A, B, C, D, E, F, G)] {
558
    def encode(data: (A, B, C, D, E, F, G)): RespCommand =
559 560
      _1.encode(data._1) ++ _2.encode(data._2) ++ _3.encode(data._3) ++ _4.encode(data._4) ++ _5.encode(data._5) ++
        _6.encode(data._6) ++ _7.encode(data._7)
D
Dejan Mijić 已提交
561
  }
562 563 564 565 566 567 568 569 570 571 572

  final case class Tuple9[-A, -B, -C, -D, -E, -F, -G, -H, -I](
    _1: Input[A],
    _2: Input[B],
    _3: Input[C],
    _4: Input[D],
    _5: Input[E],
    _6: Input[F],
    _7: Input[G],
    _8: Input[H],
    _9: Input[I]
D
Dejan Mijić 已提交
573
  ) extends Input[(A, B, C, D, E, F, G, H, I)] {
574
    def encode(data: (A, B, C, D, E, F, G, H, I)): RespCommand =
575 576
      _1.encode(data._1) ++ _2.encode(data._2) ++ _3.encode(data._3) ++ _4.encode(data._4) ++ _5.encode(data._5) ++
        _6.encode(data._6) ++ _7.encode(data._7) ++ _8.encode(data._8) ++ _9.encode(data._9)
D
Dejan Mijić 已提交
577
  }
578

579 580 581 582 583 584 585 586 587 588 589 590
  final case class Tuple10[-A, -B, -C, -D, -E, -F, -G, -H, -I, -J](
    _1: Input[A],
    _2: Input[B],
    _3: Input[C],
    _4: Input[D],
    _5: Input[E],
    _6: Input[F],
    _7: Input[G],
    _8: Input[H],
    _9: Input[I],
    _10: Input[J]
  ) extends Input[(A, B, C, D, E, F, G, H, I, J)] {
591
    def encode(data: (A, B, C, D, E, F, G, H, I, J)): RespCommand =
592 593 594 595 596
      _1.encode(data._1) ++ _2.encode(data._2) ++ _3.encode(data._3) ++ _4.encode(data._4) ++
        _5.encode(data._5) ++ _6.encode(data._6) ++ _7.encode(data._7) ++ _8.encode(data._8) ++
        _9.encode(data._9) ++ _10.encode(data._10)
  }

P
Paul Daniels 已提交
597
  final case class Tuple11[-A, -B, -C, -D, -E, -F, -G, -H, -I, -J, -K](
D
Dejan Mijić 已提交
598 599 600 601 602
    _1: Input[A],
    _2: Input[B],
    _3: Input[C],
    _4: Input[D],
    _5: Input[E],
P
Paul Daniels 已提交
603 604 605 606 607 608
    _6: Input[F],
    _7: Input[G],
    _8: Input[H],
    _9: Input[I],
    _10: Input[J],
    _11: Input[K]
D
Dejan Mijić 已提交
609
  ) extends Input[(A, B, C, D, E, F, G, H, I, J, K)] {
610
    def encode(data: (A, B, C, D, E, F, G, H, I, J, K)): RespCommand =
D
Dejan Mijić 已提交
611 612 613 614 615 616
      _1.encode(data._1) ++ _2.encode(data._2) ++ _3.encode(data._3) ++ _4.encode(data._4) ++
        _5.encode(data._5) ++ _6.encode(data._6) ++ _7.encode(data._7) ++ _8.encode(data._8) ++
        _9.encode(data._9) ++ _10.encode(data._10) ++ _11.encode(data._11)
  }

  case object UpdateInput extends Input[Update] {
617
    def encode(data: Update): RespCommand =
618
      RespCommand(RespCommandArgument.Unknown(data.asString))
D
Dejan Mijić 已提交
619 620
  }

621 622
  final case class GetExPersistInput[K: BinaryCodec]() extends Input[(K, Boolean)] {
    def encode(data: (K, Boolean)): RespCommand =
623
      RespCommand(
624 625
        if (data._2) Chunk(RespCommandArgument.Key(data._1), RespCommandArgument.Literal("PERSIST"))
        else Chunk(RespCommandArgument.Key(data._1))
626
      )
梦境迷离's avatar
梦境迷离 已提交
627
  }
628

629 630
  final case class GetExInput[K: BinaryCodec]() extends Input[(K, Expire, Duration)] {
    def encode(data: (K, Expire, Duration)): RespCommand =
梦境迷离's avatar
梦境迷离 已提交
631 632
      data match {
        case (key, Expire.SetExpireSeconds, duration) =>
633 634 635
          RespCommand(RespCommandArgument.Key(key), RespCommandArgument.Literal("EX")) ++ DurationSecondsInput.encode(
            duration
          )
梦境迷离's avatar
梦境迷离 已提交
636
        case (key, Expire.SetExpireMilliseconds, duration) =>
637 638
          RespCommand(RespCommandArgument.Key(key), RespCommandArgument.Literal("PX")) ++ DurationMillisecondsInput
            .encode(duration)
梦境迷离's avatar
梦境迷离 已提交
639 640 641
      }
  }

642 643
  final case class GetExAtInput[K: BinaryCodec]() extends Input[(K, ExpiredAt, Instant)] {
    def encode(data: (K, ExpiredAt, Instant)): RespCommand =
梦境迷离's avatar
梦境迷离 已提交
644 645
      data match {
        case (key, ExpiredAt.SetExpireAtSeconds, instant) =>
646 647 648
          RespCommand(RespCommandArgument.Key(key), RespCommandArgument.Literal("EXAT")) ++ TimeSecondsInput.encode(
            instant
          )
梦境迷离's avatar
梦境迷离 已提交
649
        case (key, ExpiredAt.SetExpireAtMilliseconds, instant) =>
650 651
          RespCommand(RespCommandArgument.Key(key), RespCommandArgument.Literal("PXAT")) ++ TimeMillisecondsInput
            .encode(instant)
梦境迷离's avatar
梦境迷离 已提交
652 653 654
      }
  }

655
  case object IdInput extends Input[Long] {
656
    def encode(data: Long): RespCommand =
657
      RespCommand(RespCommandArgument.Literal("ID"), RespCommandArgument.Unknown(data.toString))
658 659
  }

660 661 662 663 664 665 666 667 668
  case object IdsInput extends Input[(Long, List[Long])] {
    def encode(data: (Long, List[Long])): RespCommand =
      RespCommand(
        Chunk.fromIterable(
          RespCommandArgument.Literal("ID") +: (data._1 :: data._2).map(id => RespCommandArgument.Unknown(id.toString))
        )
      )
  }

669
  case object UnblockBehaviorInput extends Input[UnblockBehavior] {
670
    def encode(data: UnblockBehavior): RespCommand =
671
      RespCommand(RespCommandArgument.Unknown(data.asString))
672 673
  }

D
Dejan Mijić 已提交
674
  final case class Varargs[-A](input: Input[A]) extends Input[Iterable[A]] {
675
    def encode(data: Iterable[A]): RespCommand =
676
      data.foldLeft(RespCommand.empty)((acc, a) => acc ++ input.encode(a))
D
Dejan Mijić 已提交
677 678
  }

679
  final case class EvalInput[-K, -V](inputK: Input[K], inputV: Input[V]) extends Input[(String, Chunk[K], Chunk[V])] {
680
    def encode(data: (String, Chunk[K], Chunk[V])): RespCommand = {
681
      val (lua, keys, args) = data
682
      val encodedScript     = RespCommand(RespCommandArgument.Unknown(lua), RespCommandArgument.Unknown(keys.size.toString))
683
      val encodedKeys = keys.foldLeft(RespCommand.empty)((acc, a) =>
684
        acc ++ inputK.encode(a).mapArguments(arg => RespCommandArgument.Key(arg.value.value))
685 686
      )
      val encodedArgs = args.foldLeft(RespCommand.empty)((acc, a) =>
687
        acc ++ inputV.encode(a).mapArguments(arg => RespCommandArgument.Value(arg.value.value))
688
      )
689 690 691 692 693
      encodedScript ++ encodedKeys ++ encodedArgs
    }
  }

  case object ScriptDebugInput extends Input[DebugMode] {
694
    def encode(data: DebugMode): RespCommand =
695
      RespCommand(RespCommandArgument.Literal(data.asString))
696 697
  }

698
  case object ScriptFlushInput extends Input[FlushMode] {
699
    def encode(data: FlushMode): RespCommand =
700
      RespCommand(RespCommandArgument.Literal(data.asString))
701 702
  }

D
Dejan Mijić 已提交
703
  case object WithScoresInput extends Input[WithScores] {
704
    def encode(data: WithScores): RespCommand =
705
      RespCommand(RespCommandArgument.Literal(data.asString))
D
Dejan Mijić 已提交
706
  }
D
Dejan Mijić 已提交
707

D
Dejan Mijić 已提交
708
  case object WithCoordInput extends Input[WithCoord] {
709
    def encode(data: WithCoord): RespCommand =
710
      RespCommand(RespCommandArgument.Literal(data.asString))
D
Dejan Mijić 已提交
711
  }
D
Dejan Mijić 已提交
712

D
Dejan Mijić 已提交
713
  case object WithDistInput extends Input[WithDist] {
714
    def encode(data: WithDist): RespCommand =
715
      RespCommand(RespCommandArgument.Literal(data.asString))
D
Dejan Mijić 已提交
716
  }
D
Dejan Mijić 已提交
717

D
Dejan Mijić 已提交
718
  case object WithHashInput extends Input[WithHash] {
719
    def encode(data: WithHash): RespCommand =
720
      RespCommand(RespCommandArgument.Literal(data.asString))
D
Dejan Mijić 已提交
721
  }
722 723

  case object WithForceInput extends Input[WithForce] {
724
    def encode(data: WithForce): RespCommand =
725
      RespCommand(RespCommandArgument.Literal(data.asString))
726 727 728
  }

  case object WithJustIdInput extends Input[WithJustId] {
729
    def encode(data: WithJustId): RespCommand =
730
      RespCommand(RespCommandArgument.Literal(data.asString))
731
  }
732 733

  case object YesNoInput extends Input[Boolean] {
734
    def encode(data: Boolean): RespCommand =
735
      RespCommand(RespCommandArgument.Literal(if (data) "YES" else "NO"))
736
  }
D
Dejan Mijić 已提交
737
}