From 4a10958731d2b95c661cae46224979cbdda96cf8 Mon Sep 17 00:00:00 2001 From: Pat Garrity Date: Sun, 3 May 2026 21:20:57 -0500 Subject: [PATCH] Deleting the old stuff oops. --- src/main/scala/gs/std/v0/Base64Decoder.scala | 36 ----- src/main/scala/gs/std/v0/Base64Encoder.scala | 43 ----- src/main/scala/gs/std/v0/Blob.scala | 49 ------ src/main/scala/gs/std/v0/ByteCount.scala | 138 ---------------- src/main/scala/gs/std/v0/CreatedAt.scala | 37 ----- src/main/scala/gs/std/v0/Decoder.scala | 13 -- src/main/scala/gs/std/v0/Encode.scala | 58 ------- src/main/scala/gs/std/v0/EncodedString.scala | 162 ------------------- src/main/scala/gs/std/v0/Encoder.scala | 44 ----- src/main/scala/gs/std/v0/HexDecoder.scala | 23 --- src/main/scala/gs/std/v0/HexEncoder.scala | 13 -- src/main/scala/gs/std/v0/MD5.scala | 108 ------------- src/main/scala/gs/std/v0/Nat.scala | 84 ---------- src/main/scala/gs/std/v0/SHA256.scala | 114 ------------- src/main/scala/gs/std/v0/Size.scala | 102 ------------ src/main/scala/gs/std/v0/UpdatedAt.scala | 37 ----- 16 files changed, 1061 deletions(-) delete mode 100644 src/main/scala/gs/std/v0/Base64Decoder.scala delete mode 100644 src/main/scala/gs/std/v0/Base64Encoder.scala delete mode 100644 src/main/scala/gs/std/v0/Blob.scala delete mode 100644 src/main/scala/gs/std/v0/ByteCount.scala delete mode 100644 src/main/scala/gs/std/v0/CreatedAt.scala delete mode 100644 src/main/scala/gs/std/v0/Decoder.scala delete mode 100644 src/main/scala/gs/std/v0/Encode.scala delete mode 100644 src/main/scala/gs/std/v0/EncodedString.scala delete mode 100644 src/main/scala/gs/std/v0/Encoder.scala delete mode 100644 src/main/scala/gs/std/v0/HexDecoder.scala delete mode 100644 src/main/scala/gs/std/v0/HexEncoder.scala delete mode 100644 src/main/scala/gs/std/v0/MD5.scala delete mode 100644 src/main/scala/gs/std/v0/Nat.scala delete mode 100644 src/main/scala/gs/std/v0/SHA256.scala delete mode 100644 src/main/scala/gs/std/v0/Size.scala delete mode 100644 src/main/scala/gs/std/v0/UpdatedAt.scala diff --git a/src/main/scala/gs/std/v0/Base64Decoder.scala b/src/main/scala/gs/std/v0/Base64Decoder.scala deleted file mode 100644 index 7cc8c1c..0000000 --- a/src/main/scala/gs/std/v0/Base64Decoder.scala +++ /dev/null @@ -1,36 +0,0 @@ -package gs.std.v0.core - -import java.{util => ju} - -/** Implementation of [[Decoder]] for Base64 strings. - * - * Supports base64-url decoding as well. - */ -object Base64Decoder extends Decoder[B64]: - private lazy val d: ju.Base64.Decoder = ju.Base64.getDecoder() - private lazy val du: ju.Base64.Decoder = ju.Base64.getUrlDecoder() - - /** @inheritDocs - */ - override def decode(input: B64): Array[Byte] = - d.decode(input.data) - - /** Decode some arbitrary string data. - * - * @param input - * The data to decode. - * @return - * The decoded bytes. - */ - def decodeUnsafe(input: String): Array[Byte] = - d.decode(input) - - /** Decode the base64-url encoded input. - * - * @param input - * The base64-url encoded data. - * @return - * The decoded bytes. - */ - def decodeUrl(input: B64Url): Array[Byte] = - du.decode(input.data) diff --git a/src/main/scala/gs/std/v0/Base64Encoder.scala b/src/main/scala/gs/std/v0/Base64Encoder.scala deleted file mode 100644 index 9c99fa1..0000000 --- a/src/main/scala/gs/std/v0/Base64Encoder.scala +++ /dev/null @@ -1,43 +0,0 @@ -package gs.std.v0.core - -import java.nio.charset.Charset -import java.nio.charset.StandardCharsets -import java.util.Base64 - -/** Implementation of [[Encoder]] for Base64. - * - * Supports base64-url encoding as well. - */ -object Base64Encoder extends Encoder[B64]: - private lazy val e: Base64.Encoder = Base64.getEncoder() - private lazy val eu: Base64.Encoder = Base64.getUrlEncoder() - - /** @inheritDocs - */ - override def encode(input: Array[Byte]): B64 = - B64(e.encodeToString(input)) - - /** Encode the given bytes using base64-url. - * - * @param input - * The input data. - * @return - * The base64-url-encoded string. - */ - def encodeUrl(input: Array[Byte]): B64Url = - B64Url(eu.encodeToString(input)) - - /** Encode the given bytes using base64-url. - * - * @param input - * The input data. - * @param charset - * The character set of the input data. - * @return - * The base64-url-encoded string. - */ - def encodeUrl( - input: String, - charset: Charset = StandardCharsets.UTF_8 - ): B64Url = - encodeUrl(input.getBytes(charset)) diff --git a/src/main/scala/gs/std/v0/Blob.scala b/src/main/scala/gs/std/v0/Blob.scala deleted file mode 100644 index b51d956..0000000 --- a/src/main/scala/gs/std/v0/Blob.scala +++ /dev/null @@ -1,49 +0,0 @@ -package gs.std.v0.core - -import java.util.Base64 - -/** Represents a blob -- some array of bytes. - * - * @param data - * The underlying data. - */ -final class Blob(private val data: Array[Byte]) extends IndexedSeq[Byte]: - - /** @inheritDocs - */ - override def apply(i: Int): Byte = byteAt(i) - - /** @inheritDocs - */ - override def length: Int = data.length - - /** @return - * The number of bytes in this blob, expressed as a count. - */ - def numberOfBytes: ByteCount = ByteCount(data.length) - - /** @inheritDocs - */ - override def equals(obj: Any): Boolean = - obj match - case other: Blob => data.sameElements(other.data) - case other: Array[Byte] => data.sameElements(other) - case _ => false - - /** @inheritDocs - */ - override def hashCode(): Int = data.hashCode() - - /** Retrieve the byte at the given index. - * - * @param index - * The index. - * @return - * The byte stored at the given index. - */ - def byteAt(index: Int): Byte = data.apply(index) - - /** @return - * This byte array, encoded as a base64 string. - */ - def base64(): String = Base64.getEncoder().encodeToString(data) diff --git a/src/main/scala/gs/std/v0/ByteCount.scala b/src/main/scala/gs/std/v0/ByteCount.scala deleted file mode 100644 index c59033d..0000000 --- a/src/main/scala/gs/std/v0/ByteCount.scala +++ /dev/null @@ -1,138 +0,0 @@ -package gs.std.v0.core - -/** Opaque type for some number of bytes (>= 0). - */ -opaque type ByteCount = Long - -/** Opaque type for some number of bytes (>= 0). - */ -object ByteCount: - - /** 0 bytes. - */ - final val Zero: ByteCount = 0 - - /** 1,000 bytes. - */ - final val OneKilobyte: ByteCount = 1000 - - /** 1,000,000 bytes. - */ - final val OneMegabyte: ByteCount = 1000000 - - /** 1,000,000,000 bytes. - */ - final val OneGigabyte: ByteCount = 1000000000 - - /** Express the given number as a byte count. All values are normalized to the - * absolute value -- negative values are coerced to positive. - * - * @param value - * The input integer. - * @return - * The [[ByteCount]] instance. - */ - def apply(value: Long): ByteCount = Math.abs(value) - - /** 1 kilobyte = 1,000 bytes - * - * @param kb - * The number of kilobytes. - * @return - * The number of bytes. - */ - def fromKilobytes(kb: Long): ByteCount = - Math.abs(kb) * 1000L - - /** 1 megabyte = 1,000,000 bytes - * - * @param mb - * The number of megabytes. - * @return - * The number of bytes. - */ - def fromMegabytes(mb: Long): ByteCount = - Math.abs(mb) * 1000000L - - /** 1 gigabyte = 1,000,000,000 bytes - * - * @param mb - * The number of gigabytes. - * @return - * The number of bytes. - */ - def fromGigabytes(gb: Long): ByteCount = - Math.abs(gb) * 1000000000 - - given CanEqual[ByteCount, ByteCount] = CanEqual.derived - - given Ordering[ByteCount] with - - /** @inheritDocs - */ - def compare( - x: ByteCount, - y: ByteCount - ): Int = - if x > y then 1 else if x == y then 0 else -1 - - extension (byteCount: ByteCount) - /** @return - * The underlying `Long`. - */ - def unwrap(): Long = byteCount - - /** @return - * The underlying `Long`. - */ - def toLong(): Long = byteCount - - /** 1 kilobyte = 1,000 bytes - * - * @return - * The number of kilobytes represented by this count. - */ - def toKilobytes(): Double = byteCount / 1000.0 - - /** 1 megabyte = 1,000,000 bytes. - * - * @return - * The number of megabytes represented by this count. - */ - def toMegabytes(): Double = byteCount / 1000000.0 - - /** 1 gigabyte = 1,000,000,000 bytes. - * - * @return - * The number of gigabytes represented by this count. - */ - def toGigabytes(): Double = byteCount / 1000000000.0 - - /** Add some count to this one. - * - * @param that - * The number to add. - * @return - * The sum of the numbers. - */ - def +(that: ByteCount): ByteCount = byteCount + that - - /** Multiply this count by some other count. - * - * @param that - * The number to multiply by. - * @return - * The product of the numbers. - */ - def *(that: ByteCount): ByteCount = byteCount * that - - /** Check if this value is the same as some number. - * - * @param value - * The number to compare against. - * @return - * True if the values are equal, false otherwise. - */ - def equal(value: Int): Boolean = byteCount == value.toLong - -end ByteCount diff --git a/src/main/scala/gs/std/v0/CreatedAt.scala b/src/main/scala/gs/std/v0/CreatedAt.scala deleted file mode 100644 index 16c0a6b..0000000 --- a/src/main/scala/gs/std/v0/CreatedAt.scala +++ /dev/null @@ -1,37 +0,0 @@ -package gs.std.v0.core - -import java.time.Instant - -/** Opaque type that represents the instant something was created. - */ -opaque type CreatedAt = Instant - -/** Opaque type that represents the instant something was created. - */ -object CreatedAt: - - /** Instantiate a new [[CreatedAt]] from the given `java.time.Instant`. - * - * @param value - * The value to semantically represent. - * @return - * The new [[CreatedAt]]. - */ - def apply(value: Instant): CreatedAt = value - - given CanEqual[CreatedAt, CreatedAt] = CanEqual.derived - - given Ordering[CreatedAt] = Ordering[Instant] - - extension (createdAt: Instant) - /** @return - * The underlying `java.time.Instant`. - */ - def unwrap(): Instant = createdAt - - /** @return - * The underlying `java.time.Instant`. - */ - def toInstant(): Instant = createdAt - -end CreatedAt diff --git a/src/main/scala/gs/std/v0/Decoder.scala b/src/main/scala/gs/std/v0/Decoder.scala deleted file mode 100644 index 3ebd2a4..0000000 --- a/src/main/scala/gs/std/v0/Decoder.scala +++ /dev/null @@ -1,13 +0,0 @@ -package gs.std.v0.core - -/** Interface for byte decoding from encoded String formats. - */ -trait Decoder[-A <: EncodedString]: - /** Decode an input string to an array of bytes. - * - * @param input - * The input to decode. - * @return - * The decoded byte array. - */ - def decode(input: A): Array[Byte] diff --git a/src/main/scala/gs/std/v0/Encode.scala b/src/main/scala/gs/std/v0/Encode.scala deleted file mode 100644 index 0059eeb..0000000 --- a/src/main/scala/gs/std/v0/Encode.scala +++ /dev/null @@ -1,58 +0,0 @@ -package gs.std.v0.core - -import java.nio.charset.Charset -import java.nio.charset.StandardCharsets - -/** Helper functions for encoding data. - */ -object Encode: - - /** Encode an array of bytes using base64. - * - * @param input - * The bytes to encode. - * @return - * The base64 string. - */ - def base64(input: Array[Byte]): B64 = Base64Encoder.encode(input) - - /** Encode a string using base64. - * - * @param input - * The string to encode. - * @param charset - * The character set of the input string. - * @return - * The base64 string. - */ - def base64( - input: String, - charset: Charset = StandardCharsets.UTF_8 - ): B64 = - Base64Encoder.encode(input, charset) - - /** Encode an array of bytes using hexadecimal. - * - * @param input - * The bytes to encode. - * @return - * The hexadecimal string. - */ - def hex(input: Array[Byte]): Hex = HexEncoder.encode(input) - - /** Encode a string using hexadecimal. - * - * @param input - * The string to encode. - * @param charset - * The character set of the input string. - * @return - * The hexadecimal string. - */ - def hex( - input: String, - charset: Charset = StandardCharsets.UTF_8 - ): Hex = - HexEncoder.encode(input, charset) - -end Encode diff --git a/src/main/scala/gs/std/v0/EncodedString.scala b/src/main/scala/gs/std/v0/EncodedString.scala deleted file mode 100644 index 372b7e5..0000000 --- a/src/main/scala/gs/std/v0/EncodedString.scala +++ /dev/null @@ -1,162 +0,0 @@ -package gs.std.v0.core - -/** Represents string-encoded data. - * - * See: - * - [[B64]] - * - [[Hex]] - */ -trait EncodedString: - /** @return - * The encoded data (expressed as a string). - */ - def data: String - - /** @return - * Decode the data to a byte array. - */ - def decode(): Array[Byte] - - /** Represents Base64-encoded data. - * - * @param data - * The encoded data. - */ - -/** Represents Base64-encoded data. - * - * @param data - * The encoded data. - */ -final class B64( - val data: String -) extends EncodedString: - /** @inheritDocs - */ - def decode(): Array[Byte] = Base64Decoder.decode(this) - - /** @inheritDocs - */ - override def equals(obj: Any): Boolean = - obj match - case other: B64 => data == other.data - - /** @inheritDocs - */ - override def hashCode(): Int = data.hashCode() - - /** @inheritDocs - */ - override def toString(): String = data - -object B64: - - /** Instantiate [[B64]] from the given string. Assumes that the input is - * base64-encoded. - * - * This function does NOT validate the input. - * - * @param data - * The encoded data. - * @return - * The new [[B64]] instance. - */ - def apply( - data: String - ): B64 = new B64(data) - - given CanEqual[B64, B64] = CanEqual.derived - -end B64 - -/** Represents Base64-url-encoded data. - * - * @param data - * The encoded data. - */ -final class B64Url( - val data: String -) extends EncodedString: - /** @inheritDocs - */ - def decode(): Array[Byte] = Base64Decoder.decodeUrl(this) - - /** @inheritDocs - */ - override def equals(obj: Any): Boolean = - obj match - case other: B64Url => data == other.data - - /** @inheritDocs - */ - override def hashCode(): Int = data.hashCode() - - /** @inheritDocs - */ - override def toString(): String = data - -object B64Url: - - /** Instantiate [[B64Url]] from the given string. Assumes that the input is - * base64-encoded. - * - * This function does NOT validate the input. - * - * @param data - * The encoded data. - * @return - * The new [[B64Url]] instance. - */ - def apply( - data: String - ): B64Url = new B64Url(data) - - given CanEqual[B64Url, B64Url] = CanEqual.derived - -end B64Url - -/** Represents Hex-encoded data. - * - * @param data - * The encoded data. - */ -final class Hex( - val data: String -) extends EncodedString: - /** @inheritDocs - */ - def decode(): Array[Byte] = HexDecoder.decode(this) - - /** @inheritDocs - */ - override def equals(obj: Any): Boolean = - obj match - case other: Hex => data == other.data - - /** @inheritDocs - */ - override def hashCode(): Int = data.hashCode() - - /** @inheritDocs - */ - override def toString(): String = data - -object Hex: - - /** Instantiate [[Hex]] from the given string. Assumes that the input is - * hex-encoded. - * - * This function does NOT validate the input. - * - * @param data - * The encoded data. - * @return - * The new [[Hex]] instance. - */ - def apply( - data: String - ): Hex = new Hex(data) - - given CanEqual[Hex, Hex] = CanEqual.derived - -end Hex diff --git a/src/main/scala/gs/std/v0/Encoder.scala b/src/main/scala/gs/std/v0/Encoder.scala deleted file mode 100644 index 1278aeb..0000000 --- a/src/main/scala/gs/std/v0/Encoder.scala +++ /dev/null @@ -1,44 +0,0 @@ -package gs.std.v0.core - -import java.nio.charset.Charset -import java.nio.charset.StandardCharsets - -/** Interface for byte encoding to String formats. - */ -trait Encoder[+A <: EncodedString]: - /** Encode an array of bytes as a string. - * - * @param input - * The bytes to encode. - * @return - * The encoded string. - */ - def encode(input: Array[Byte]): A - - /** Encode a string as a string. - * - * @param input - * The string to encode. - * @param charset - * The character set of the input string. - * @return - * The encoded string. - */ - def encode( - input: String, - charset: Charset = StandardCharsets.UTF_8 - ): A = encode(input.getBytes(charset)) - -object Encoder: - - /** @return - * The [[Base64Encoder]], typed to `Encoder[Encoded]`. - */ - def base64(): Encoder[EncodedString] = Base64Encoder - - /** @return - * The [[HexEncoder]], typed to `Encoder[Encoded]`. - */ - def hex(): Encoder[EncodedString] = HexEncoder - -end Encoder diff --git a/src/main/scala/gs/std/v0/HexDecoder.scala b/src/main/scala/gs/std/v0/HexDecoder.scala deleted file mode 100644 index c48c1e3..0000000 --- a/src/main/scala/gs/std/v0/HexDecoder.scala +++ /dev/null @@ -1,23 +0,0 @@ -package gs.std.v0.core - -import java.util.HexFormat - -/** Implementation of [[Decoder]] for Hexadecimal strings. - */ -object HexDecoder extends Decoder[Hex]: - private lazy val h: HexFormat = HexFormat.of() - - /** @inheritDocs - */ - override def decode(input: Hex): Array[Byte] = - h.parseHex(input.data) - - /** Decode some arbitrary string data. - * - * @param input - * The data to decode. - * @return - * The decoded bytes. - */ - def decodeUnsafe(input: String): Array[Byte] = - h.parseHex(input) diff --git a/src/main/scala/gs/std/v0/HexEncoder.scala b/src/main/scala/gs/std/v0/HexEncoder.scala deleted file mode 100644 index 7430199..0000000 --- a/src/main/scala/gs/std/v0/HexEncoder.scala +++ /dev/null @@ -1,13 +0,0 @@ -package gs.std.v0.core - -import java.util.HexFormat - -/** Implementation of [[Encoder]] for Hexadecimal strings. - */ -object HexEncoder extends Encoder[Hex]: - private lazy val h: HexFormat = HexFormat.of() - - /** @inheritDocs - */ - override def encode(input: Array[Byte]): Hex = - Hex(h.formatHex(input)) diff --git a/src/main/scala/gs/std/v0/MD5.scala b/src/main/scala/gs/std/v0/MD5.scala deleted file mode 100644 index e4866d5..0000000 --- a/src/main/scala/gs/std/v0/MD5.scala +++ /dev/null @@ -1,108 +0,0 @@ -package gs.std.v0.core - -import java.nio.charset.Charset -import java.nio.charset.StandardCharsets -import java.security.MessageDigest - -/** Opaque type representing a MD5 hash. - */ -opaque type MD5 = Array[Byte] - -/** Opaque type representing a MD5 hash. - */ -object MD5: - - /** MD5 hashes are exactly 16 bytes. - */ - final val NumberOfBytes: ByteCount = ByteCount(16) - - /** The algorithm name is "MD5". - */ - final val Algorithm: String = "MD5" - - /** Instantiate a [[MD5]] from the given byte array. This function does not - * know whether the array is actually a calculated hash. - * - * Typically used for loading pre-validated hashes (e.g. from a database). - * - * @param bytes - * The bytes - must contain exactly 16 bytes. - * @return - * The new [[MD5]] instance. - */ - def fromBytes(bytes: Array[Byte]): MD5 = - if NumberOfBytes.equal(bytes.length) then bytes - else - throw IllegalArgumentException( - s"MD5 values must be exactly $NumberOfBytes bytes." - ) - - /** Calculate the MD5 hash for the given byte array. - * - * @param data - * The byte array. - * @return - * The calculated [[MD5]]. - */ - def calculate(data: Array[Byte]): MD5 = - MessageDigest.getInstance(Algorithm).digest(data) - - /* Calculate the MD5 hash for the given string. - * - * @param data The string data. - * @param charset The character set of the string. Defaults to UTF-8. - * @return The calculated [[MD5]]. */ - def calculate( - data: String, - charset: Charset = StandardCharsets.UTF_8 - ): MD5 = - calculate(data.getBytes(charset)) - - extension (md5: MD5) - /** @return - * The underlying byte array. - */ - def unwrap(): Array[Byte] = md5 - - /** @return - * The underlying byte array. - */ - def toBytes(): Array[Byte] = md5 - - /** Get the byte at the given index (0 to 15). - * - * Throws an exception if an out-of-bound index is given. - * - * @param index - * The byte index (0 to 15). - * @return - * The byte at the specified index. - */ - def getByte(index: Int): Byte = - if index < 0 || index >= NumberOfBytes.unwrap() then - throw IndexOutOfBoundsException( - s"Index $index out of MD5 bound of $NumberOfBytes bytes." - ) - else md5.apply(index) - - /** Determine if this hash is the same as some other hash. Compares each - * byte in order. - * - * @param other - * The [[MD5]] to compare against. - * @return - * True if the hashes are identical, false otherwise. - */ - def isSame(other: MD5): Boolean = md5.sameElements(other) - - /** @return - * This hash encoded to a Base64 string. - */ - def base64(): EncodedString = Base64Encoder.encode(md5) - - /** @return - * This hash encoded to a Hexadecimal string. - */ - def hex(): EncodedString = HexEncoder.encode(md5) - -end MD5 diff --git a/src/main/scala/gs/std/v0/Nat.scala b/src/main/scala/gs/std/v0/Nat.scala deleted file mode 100644 index d3a586c..0000000 --- a/src/main/scala/gs/std/v0/Nat.scala +++ /dev/null @@ -1,84 +0,0 @@ -package gs.std.v0.core - -/** Opaque type for the natural numbers (including 0). - */ -opaque type Nat = Int - -/** Opaque type for the natural numbers (including 0). - */ -object Nat: - - sealed trait Invalid - object Invalid extends Invalid - - /** The number 0. - */ - final val Zero: Nat = 0 - - /** The number 1. - */ - final val One: Nat = 1 - - /** Express the given integer as a natural number. - * - * Throws an `IllegalArgumentException` if a negative value is given as - * input. - * - * @param value - * The input integer. - * @return - * The [[Nat]] instance. - */ - def apply(value: Int): Nat = - if value >= 0 then value - else throw new IllegalArgumentException("Nat values must be 0 or greater.") - - def validate(value: Int): Either[Invalid, Nat] = - if value >= 0 then Right(value) else Left(Invalid) - - given CanEqual[Nat, Nat] = CanEqual.derived - - given Ordering[Nat] with - - /** @inheritDocs - */ - def compare( - x: Nat, - y: Nat - ): Int = x - y - - extension (nat: Nat) - /** @return - * The underlying integer. - */ - def unwrap(): Int = nat - - /** @return - * The next integer. - */ - def next(): Nat = nat + 1 - - /** @return - * The next integer. - */ - def increment(): Nat = nat + 1 - - /** Add some natural number to this one. - * - * @param that - * The number to add. - * @return - * The sum of the numbers. - */ - def +(that: Nat): Nat = nat + that - - /** Multiply this natural number by some other natural number. - * - * @param that - * The number to multiply by. - * @return - * The product of the numbers. - */ - def *(that: Nat): Nat = nat * that - -end Nat diff --git a/src/main/scala/gs/std/v0/SHA256.scala b/src/main/scala/gs/std/v0/SHA256.scala deleted file mode 100644 index 90f7198..0000000 --- a/src/main/scala/gs/std/v0/SHA256.scala +++ /dev/null @@ -1,114 +0,0 @@ -package gs.std.v0.core - -import java.nio.charset.Charset -import java.nio.charset.StandardCharsets -import java.security.MessageDigest - -/** Opaque type representing a SHA-256 hash. - * - * The actual underlying type is an array of bytes. - */ -opaque type SHA256 = Array[Byte] - -/** Opaque type representing a SHA-256 hash. - */ -object SHA256: - - /** SHA-256 hashes are exactly 32 bytes. - */ - final val NumberOfBytes: ByteCount = ByteCount(32) - - /** The algorithm name is "SHA-256". - */ - final val Algorithm: String = "SHA-256" - - /** Instantiate a [[SHA256]] from the given byte array. This function does not - * know whether the array is actually a calculated hash. - * - * Typically used for loading pre-validated hashes (e.g. from a database). - * - * @param bytes - * The bytes - must contain exactly 32 bytes. - * @return - * The new [[SHA256]] instance. - */ - def fromBytes(bytes: Array[Byte]): SHA256 = - if NumberOfBytes.equal(bytes.length) then bytes - else - throw IllegalArgumentException( - s"SHA-256 values must be exactly $NumberOfBytes bytes." - ) - - /** Calculate the SHA-256 hash for the given byte array. - * - * @param data - * The byte array. - * @return - * The calculated [[SHA256]]. - */ - def calculate(data: Array[Byte]): SHA256 = - MessageDigest.getInstance(Algorithm).digest(data) - - /** Calculate the SHA-256 hash for the given string. - * - * @param data - * The string data. - * @param charset - * The character set of the string. Defaults to UTF-8. - * @return - * The calculated [[SHA256]]. - */ - def calculate( - data: String, - charset: Charset = StandardCharsets.UTF_8 - ): SHA256 = - calculate(data.getBytes(charset)) - - extension (sha: SHA256) - /** @return - * The underlying byte array. - */ - def unwrap(): Array[Byte] = sha - - /** @return - * The underlying byte array. - */ - def toBytes(): Array[Byte] = sha - - /** Get the byte at the given index (0 to 31). - * - * Throws an exception if an out-of-bound index is given. - * - * @param index - * The byte index (0 to 31). - * @return - * The byte at the specified index. - */ - def getByte(index: Int): Byte = - if index < 0 || index >= NumberOfBytes.unwrap() then - throw IndexOutOfBoundsException( - s"Index $index out of SHA-256 bound of $NumberOfBytes bytes." - ) - else sha.apply(index) - - /** Determine if this hash is the same as some other hash. Compares each - * byte in order. - * - * @param other - * The [[SHA256]] to compare against. - * @return - * True if the hashes are identical, false otherwise. - */ - def isSame(other: SHA256): Boolean = sha.sameElements(other) - - /** @return - * This hash encoded to a Base64 string. - */ - def base64(): EncodedString = Base64Encoder.encode(sha) - - /** @return - * This hash encoded to a Hexadecimal string. - */ - def hex(): EncodedString = HexEncoder.encode(sha) - -end SHA256 diff --git a/src/main/scala/gs/std/v0/Size.scala b/src/main/scala/gs/std/v0/Size.scala deleted file mode 100644 index c00cbec..0000000 --- a/src/main/scala/gs/std/v0/Size.scala +++ /dev/null @@ -1,102 +0,0 @@ -package gs.std.v0.core - -/** Opaque type for collection sizes. Values are guaranteed to be 0 or greater. - */ -opaque type Size = Int - -/** Opaque type for collection sizes. Values are guaranteed to be 0 or greater. - */ -object Size: - - sealed trait Invalid - object Invalid extends Invalid - - /** The size 0. - */ - final val Zero: Size = 0 - - /** The size 1. - */ - final val One: Size = 1 - - /** Express the given integer as a size. - * - * Throws an `IllegalArgumentException` if a negative value is given as - * input. - * - * @param value - * The input integer. - * @return - * The [[Size]] instance. - */ - def apply(value: Int): Size = - if value >= 0 then value - else throw new IllegalArgumentException("Size values must be 0 or greater.") - - def validate(value: Int): Either[Invalid, Size] = - if value >= 0 then Right(value) else Left(Invalid) - - /** Express the size of any collection. - * - * @param iter - * The collection. - * @return - * The size of the collection. - */ - def of(iter: Iterable[?]): Size = iter.size - - /** Express the size of any array. - * - * @param arr - * The array. - * @return - * The size of the array. - */ - def of(arr: Array[?]): Size = arr.length - - given CanEqual[Size, Size] = CanEqual.derived - - given Ordering[Size] with - - /** @inheritDocs - */ - def compare( - x: Size, - y: Size - ): Int = x - y - - extension (size: Size) - /** @return - * The underlying integer. - */ - def unwrap(): Int = size - - /** @return - * The next value. - */ - def next(): Size = size + 1 - - /** @return - * The next value. - */ - def increment(): Size = size + 1 - - /** Add some size to this one. - * - * @param that - * The number to add. - * @return - * The sum of the numbers. - */ - def +(that: Size): Size = size + that - - /** Multiply this size by some other size. - * - * @param that - * The number to multiply by. - * @return - * The product of the numbers. - */ - def *(that: Size): Size = size * that - -end Size diff --git a/src/main/scala/gs/std/v0/UpdatedAt.scala b/src/main/scala/gs/std/v0/UpdatedAt.scala deleted file mode 100644 index 8244602..0000000 --- a/src/main/scala/gs/std/v0/UpdatedAt.scala +++ /dev/null @@ -1,37 +0,0 @@ -package gs.std.v0.core - -import java.time.Instant - -/** Opaque type that represents the instant something was updated. - */ -opaque type UpdatedAt = Instant - -/** Opaque type that represents the instant something was updated. - */ -object UpdatedAt: - - /** Instantiate a new [[UpdatedAt]] from the given `java.time.Instant`. - * - * @param value - * The value to semantically represent. - * @return - * The new [[UpdatedAt]]. - */ - def apply(value: Instant): UpdatedAt = value - - given CanEqual[UpdatedAt, UpdatedAt] = CanEqual.derived - - given Ordering[UpdatedAt] = Ordering[Instant] - - extension (updatedAt: Instant) - /** @return - * The underlying `java.time.Instant`. - */ - def unwrap(): Instant = updatedAt - - /** @return - * The underlying `java.time.Instant`. - */ - def toInstant(): Instant = updatedAt - -end UpdatedAt