mirror of
https://github.com/apple/pkl.git
synced 2026-01-11 22:30:54 +01:00
Introduces Bytes class (#1019)
This introduces a new `Bytes` standard library class, for working with binary data. * Add Bytes class to the standard library * Change CLI to eval `output.bytes` * Change code generators to map Bytes to respective underlying type * Add subscript and concat operator support * Add binary encoding for Bytes * Add PCF and Plist rendering for Bytes Co-authored-by: Kushal Pisavadia <kushi.p@gmail.com>
This commit is contained in:
146
stdlib/base.pkl
146
stdlib/base.pkl
@@ -104,6 +104,7 @@ abstract external class Module {
|
||||
else if (format == "yaml") new YamlRenderer {}
|
||||
else throw("Unknown output format: `\(format)`. Supported formats are `json`, `jsonnet`, `pcf`, `plist`, `properties`, `textproto`, `xml`, `yaml`.")
|
||||
text = renderer.renderDocument(value)
|
||||
bytes = text.encodeToBytes("UTF-8")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,8 +218,14 @@ open class FileOutput {
|
||||
/// The renderer for [value].
|
||||
renderer: ValueRenderer = new PcfRenderer {}
|
||||
|
||||
/// The final rendered output.
|
||||
/// The textual rendered output.
|
||||
text: String = renderer.renderDocument(value)
|
||||
|
||||
/// The underlying byte output.
|
||||
///
|
||||
/// If unset, defaults to the UTF-8 encoding of [text].
|
||||
@Since { version = "0.29.0" }
|
||||
bytes: Bytes = text.encodeToBytes("UTF-8")
|
||||
}
|
||||
|
||||
/// The contents and appearance of a module's output.
|
||||
@@ -513,28 +520,37 @@ class Resource {
|
||||
/// The text content of this resource.
|
||||
text: String
|
||||
|
||||
/// The bytes of this resource.
|
||||
@Since { version = "0.29.0" }
|
||||
bytes: Bytes
|
||||
|
||||
/// The content of this resource in Base64.
|
||||
base64: String
|
||||
@Deprecated { since = "0.29.0"; message = "Use bytes.base64 instead" }
|
||||
hidden base64: String = bytes.base64
|
||||
|
||||
/// The [MD5](https://en.wikipedia.org/wiki/MD5)
|
||||
/// hash of this resource as hexadecimal string.
|
||||
///
|
||||
/// MD5 is cryptographically broken and should not be used for secure applications.
|
||||
external md5: String
|
||||
@Deprecated { since = "0.29.0"; message = "Use bytes.md5 instead" }
|
||||
hidden fixed md5: String = bytes.md5
|
||||
|
||||
/// The [SHA-1](https://en.wikipedia.org/wiki/SHA-1)
|
||||
/// hash of this resource as hexadecimal string.
|
||||
///
|
||||
/// SHA-1 is cryptographically broken and should not be used for secure applications.
|
||||
external sha1: String
|
||||
@Deprecated { since = "0.29.0"; message = "Use bytes.sha1 instead" }
|
||||
hidden fixed sha1: String = bytes.sha1
|
||||
|
||||
/// The [SHA-256](https://en.wikipedia.org/wiki/SHA-2)
|
||||
/// cryptographic hash of this resource as hexadecimal string.
|
||||
external sha256: String
|
||||
@Deprecated { since = "0.29.0"; message = "Use bytes.sha256 instead" }
|
||||
hidden fixed sha256: String = bytes.sha256
|
||||
|
||||
/// The first 64 bits of the [SHA-256](https://en.wikipedia.org/wiki/SHA-2)
|
||||
/// cryptographic hash of this resource.
|
||||
external sha256Int: Int
|
||||
@Deprecated { since = "0.29.0"; message = "Use bytes.sha256Int instead" }
|
||||
hidden fixed sha256Int: Int = bytes.sha256Int
|
||||
}
|
||||
|
||||
/// Common base class of [Int] and [Float].
|
||||
@@ -1123,6 +1139,16 @@ external class String extends Any {
|
||||
/// Tells if this string is a valid regular expression according to [Regex].
|
||||
external isRegex: Boolean
|
||||
|
||||
/// Tells if this is a valid base64-encoded string.
|
||||
///
|
||||
/// Facts:
|
||||
/// ```
|
||||
/// "AQIDBA==".isBase64
|
||||
/// !"hello there".isBase64
|
||||
/// ```
|
||||
@Since { version = "0.29.0" }
|
||||
external isBase64: Boolean
|
||||
|
||||
/// The [MD5](https://en.wikipedia.org/wiki/MD5)
|
||||
/// hash of this string's UTF-8 byte sequence
|
||||
/// as hexadecimal string.
|
||||
@@ -1156,6 +1182,15 @@ external class String extends Any {
|
||||
/// ```
|
||||
external base64Decoded: String
|
||||
|
||||
/// Converts this base64-format string into [Bytes].
|
||||
///
|
||||
/// Facts:
|
||||
/// ```
|
||||
/// "AQIDBA==".base64DecodedBytes = Bytes(1, 2, 3, 4)
|
||||
/// ```
|
||||
@Since { version = "0.29.0" }
|
||||
external base64DecodedBytes: Bytes
|
||||
|
||||
/// The Unicode characters in this string.
|
||||
///
|
||||
/// Facts:
|
||||
@@ -1433,8 +1468,25 @@ external class String extends Any {
|
||||
///
|
||||
/// Returns [null] if this string is neither `"true"` nor `"false"` (case-insensitive).
|
||||
external function toBooleanOrNull(): Boolean?
|
||||
|
||||
/// Returns the bytes of this string, encoded using [charset].
|
||||
///
|
||||
/// Facts:
|
||||
/// ```
|
||||
/// "Parrot".encodeToBytes("UTF-8") == Bytes(80, 97, 114, 114, 111, 116)
|
||||
/// ```
|
||||
@Since { version = "0.29.0" }
|
||||
external function encodeToBytes(charset: Charset): Bytes
|
||||
}
|
||||
|
||||
/// An identifier for a [character encoding](https://en.wikipedia.org/wiki/Character_encoding).
|
||||
///
|
||||
/// * `"UTF-8"`: <https://en.wikipedia.org/wiki/UTF-8>
|
||||
/// * `"UTF-16"`: <https://en.wikipedia.org/wiki/UTF-16>
|
||||
/// * `"ISO-8859-1"` (also known as latin1): <https://en.wikipedia.org/wiki/ISO/IEC_8859-1>
|
||||
@Since { version = "0.29.0" }
|
||||
typealias Charset = "UTF-8"|"UTF-16"|"ISO-8859-1"
|
||||
|
||||
/// A string representing a [URI](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier).
|
||||
typealias Uri = String
|
||||
|
||||
@@ -3042,6 +3094,12 @@ external class List<out Element> extends Collection<Element> {
|
||||
external function toListing(): Listing<Element>
|
||||
|
||||
external function toDynamic(): Dynamic
|
||||
|
||||
/// Converts this list to [Bytes].
|
||||
///
|
||||
/// Throws a type error if any of its elements are not [UInt8].
|
||||
@Since { version = "0.29.0" }
|
||||
external function toBytes(): Bytes
|
||||
}
|
||||
|
||||
/// Creates a set containing the given [elements].
|
||||
@@ -3301,3 +3359,79 @@ external class Map<out Key, out Value> extends Any {
|
||||
/// Converts this map to a [Mapping].
|
||||
external function toMapping(): Mapping<Key, Value>
|
||||
}
|
||||
|
||||
/// Creates [Bytes] from the given numbers.
|
||||
///
|
||||
/// Examples:
|
||||
/// ```
|
||||
/// bytes = Bytes(0x1, 0x2, 0x3, 0x4)
|
||||
/// ```
|
||||
@Since { version = "0.29.0" }
|
||||
external const function Bytes(values: VarArgs<UInt8>): Bytes
|
||||
|
||||
/// A sequence of [UInt8] values.
|
||||
///
|
||||
/// Bytes can hold up to [math.maxInt] amount of bytes.
|
||||
///
|
||||
/// The following operators are supported for [Bytes]:
|
||||
/// ```
|
||||
/// bytes1 + bytes2 // concatenation
|
||||
/// bytes[3] // subscript
|
||||
/// ```
|
||||
///
|
||||
/// For other list-like procedures, convert this into a [List] using [toList()].
|
||||
@Since { version = "0.29.0" }
|
||||
external class Bytes extends Any {
|
||||
/// The length of these bytes.
|
||||
external length: Int
|
||||
|
||||
/// The number of bytes as [DataSize].
|
||||
external size: DataSize
|
||||
|
||||
/// The bytes in base64 encoding.
|
||||
external base64: String(isBase64)
|
||||
|
||||
/// The bytes in hexadecimal encoding.
|
||||
external hex: String
|
||||
|
||||
/// The [MD5](https://en.wikipedia.org/wiki/MD5) hash of these bytes as hexadecimal string.
|
||||
///
|
||||
/// MD5 is cryptographically broken and should not be used for secure applications.
|
||||
external md5: String
|
||||
|
||||
/// The [SHA-1](https://en.wikipedia.org/wiki/SHA-1) hash of these bytes as hexadecimal string.
|
||||
///
|
||||
/// SHA-1 is cryptographically broken and should not be used for secure applications.
|
||||
external sha1: String
|
||||
|
||||
/// The [SHA-256](https://en.wikipedia.org/wiki/SHA-2) cryptographic hash of these bytes as
|
||||
/// hexadecimal string.
|
||||
external sha256: String
|
||||
|
||||
/// The first 64 bits of the [SHA-256](https://en.wikipedia.org/wiki/SHA-2) cryptographic hash of
|
||||
/// these bytes.
|
||||
external sha256Int: Int
|
||||
|
||||
/// Returns the element at [index].
|
||||
///
|
||||
/// Returns [null] if [index] is outside the bounds of these Bytes.
|
||||
///
|
||||
/// Facts:
|
||||
/// ```
|
||||
/// Bytes(3, 9, 6).getOrNull(0) == 3
|
||||
/// Bytes(3, 9, 6).getOrNull(1) == 9
|
||||
/// Bytes(3, 9, 6).getOrNull(2) == 6
|
||||
/// Bytes(3, 9, 6).getOrNull(-1) == null
|
||||
/// Bytes(3, 9, 6).getOrNull(3) == null
|
||||
/// Bytes(3, 9, 6).getOrNull(99) == null
|
||||
/// ```
|
||||
external function getOrNull(index: Int): UInt8?
|
||||
|
||||
/// Converts these bytes into a string using the given [charset].
|
||||
///
|
||||
/// Throws if these bytes are invalid according to the given [charset].
|
||||
external function decodeToString(charset: Charset): String
|
||||
|
||||
/// Converts these bytes into a [List].
|
||||
external function toList(): List<UInt8>
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user