std.crypto.pem.PemFile
type pub PemFile[I: mut + Read[E], E]A parser/iterator over the sections in a PEM file.
Parsing is done using one of the following methods:
PemFile.next: parses and returns the next section found, wrapped in anItemenumPemFile.next_certificate: returns the next certificatePemFile.next_private_key: returns the next private key
Examples
Parsing the next item in a PEM file:
import std.crypto.pem (PemFile)
import std.io (Buffer)
let input = '
-----BEGIN PRIVATE KEY-----
aGVsbG8=
-----END PRIVATE KEY-----
'
let parser = PemFile.new(Buffer.new(input))
parser.next # => Option.Some(Result.Ok(Item.PrivateKey(...)))
Parsing the next certificate, skipping anything that comes before it:
import std.crypto.pem (PemFile)
import std.io (Buffer)
let input = '
-----BEGIN PRIVATE KEY-----
aGVsbG8=
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
aGVsbG8=
-----END CERTIFICATE-----
'
let parser = PemFile.new(Buffer.new(input))
parser.next_certificate # => Result.Ok(Option.Some(Certificate(...)))
Static methods
new
Show source codeHide source code
fn pub static new(input: I) -> PemFile[I, E] {
PemFile(
input: BufferedReader.new(input),
line: 1,
buffer: ByteArray.new,
decoder: Decoder.new,
)
}fn pub static new(input: I: mut) -> PemFile[I: mut, E]Returns a new parser that parses data from input.
Instance methods
all?
Show source codeHide source code
fn pub mut all?(func: fn (T) -> Bool) -> Bool {
loop {
match self.next {
case Some(v) -> if !func.call(v) { return false }
case _ -> return true
}
}
}fn pub mut all?(func: fn (T) -> Bool) -> BoolReturns true if the supplied func returns true for all values in
self.
This method stops iterating over the values after the first value for which
the closure returns false.
Examples
Checking if all values in an Iter match a condition:
[10, 20].iter.all? fn (value) { value.positive? } # => true
[-1, 20].iter.all? fn (value) { value.positive? } # => false
any?
Show source codeHide source code
fn pub mut any?(func: fn (T) -> Bool) -> Bool {
loop {
match self.next {
case Some(v) -> if func.call(v) { return true }
case _ -> return false
}
}
}fn pub mut any?(func: fn (T) -> Bool) -> BoolReturns true if self contains any value for which the func argument
returned true.
This method stops iterating over the values after the first matching value.
Examples
Checking if an Iter contains a value:
[10, 20, 30].iter.any? fn (value) { value >= 20 } # => true
chain
Show source codeHide source code
fn pub move chain[I: mut + Iter[T]](other: I) -> Stream[T] {
let mut iter_left = true
Stream.new(fn move {
if iter_left {
let item = self.next
if item.some? { return item } else { iter_left = false }
}
other.next
})
}fn pub move chain[I: mut + Iter[T]](other: I: mut) -> Stream[T]Join two Iter objects together, one after another.
Examples
let a = [10, 20, 30]
let b = [40, 50, 60]
a.iter.chain(b.iter).to_array == [10, 20, 30, 40, 50, 60] # => true
chunks
Show source codeHide source code
fn pub move chunks(size: Int) -> Stream[Array[T]] {
Stream.new(fn move {
let chunk = []
while chunk.size < size {
match self.next {
case Some(val) -> chunk.push(val)
case _ -> break
}
}
if chunk.empty? { Option.None } else { Option.Some(chunk) }
})
}fn pub move chunks(size: Int) -> Stream[Array[T]]Returns an Iter that produces chunks of values.
Each chunk is up to the amount specified by the size argument. If the
number of values can't be evenly divided, the last chunk may contain fewer
than size elements.
count
Show source codeHide source code
fn pub move count -> Int {
reduce(0, fn (count, _) { count + 1 })
}fn pub move count -> IntReturns the number of values remaining in this iterator.
This method advances the iterator to the end.
Examples
[1, 2, 3].iter.count # => 3
find
Show source codeHide source code
fn pub mut find(func: fn (ref T) -> Bool) -> Option[T] {
loop {
match self.next {
case Some(v) -> if func.call(v) { return Option.Some(v) }
case _ -> return Option.None
}
}
}fn pub mut find(func: fn (ref T) -> Bool) -> Option[T]Returns the first value for which the supplied Block returns true.
This method will advance the Iter until either a value is found or we
run out of values.
Examples
Finding the first number greated than 50 in an Array:
let numbers = [10, 20, 50, 80]
numbers.iter.find fn (number) { number > 50 } # => 80
find_map
Show source codeHide source code
fn pub mut find_map[R](func: fn (T) -> Option[R]) -> Option[R] {
loop {
match self.next {
case Some(v) -> {
match func.call(v) {
case Some(r) -> return Option.Some(r)
case _ -> {}
}
}
case _ -> return Option.None
}
}
}fn pub mut find_map[R](func: fn (T) -> Option[R]) -> Option[R]Returns an Iter that combines find with map.
For each value in self, the supplied closure is called. If the closure
returns a Some, the value is returned an iteration stops.
Examples
let vals = [10, 20, 30]
let val = vals.into_iter.find_map fn (v) {
if v == 20 { Option.Some(v.to_string) } else { Option.None }
}
val # => Option.Some('20')
flat_map
Show source codeHide source code
fn pub move flat_map[V, I: mut + Iter[V]](func: fn (T) -> I) -> Stream[V] {
let mut iter_opt: Option[I] = Option.None
Stream.new(fn move {
loop {
match iter_opt.as_mut {
case Some(v) -> {
match v.next {
case Some(v) -> return Option.Some(v)
case _ -> {}
}
}
case _ -> {}
}
match self.next {
case Some(v) -> iter_opt = Option.Some(func.call(v))
case _ -> return Option.None
}
}
})
}fn pub move flat_map[V, I: mut + Iter[V]](func: fn (T) -> I: mut) -> Stream[V]Returns an Iter that maps every value into a new Iter and flattens these
iterators.
This allows you to take for example an Iter[Foo] and for each Foo
produce and flatten a Iter[Bar] such that the final iterator yields all
the individual Bar values instead of the Iter[Bar] iterators.
Examples
['foo', 'bar']
.into_iter
.flat_map(fn (str) { str.chars })
.to_array # => ['f', 'o', 'o', 'b', 'a', 'r']
into_iter
Show source codeHide source code
fn pub move into_iter -> Self {
self
}fn pub move into_iter -> SelfTakes ownership of self and returns it.
This method exists such that one can use a for loop with an existing
iterator, as for loops call into_iter on the collection to iterate over.
last
Show source codeHide source code
fn pub move last -> Option[T] {
reduce(Option.None, fn (_, val) { Option.Some(val) })
}fn pub move last -> Option[T]Returns the last value produced by this iterator.
Examples
[1, 2, 3].iter.last # => Option.Some(3)
map
Show source codeHide source code
fn pub move map[R](func: fn (T) -> R) -> Stream[R] {
Stream.new(fn move { self.next.map(fn (v) { func.call(v) }) })
}fn pub move map[R](func: fn (T) -> R) -> Stream[R]Returns an Iter that transforms values of type T to values of type
R.
Examples
Multiplying the numbers in an Array:
let values = [1, 2, 3]
values.iter.map fn (n) { n * 2 }.to_array # => [2, 4, 6]
next
Show source codeHide source code
fn pub mut next -> Option[Result[Item, ParseError[E]]] {
match parse {
case Ok(Some(v)) -> Option.Some(Result.Ok(v))
case Ok(_) -> Option.None
case Error(e) -> Option.Some(Result.Error(e))
}
}fn pub mut next -> Option[Result[Item, ParseError[E]]]Returns the next item (a certificate, private key, etc) found in the input stream.
Errors
If parsing fails, the return value is an Option wrapping a ParseError
error. In this case one should stop the parsing process, as the parser's
internal state isn't reset upon encountering an error and continuing to use
it may yield unexpected results.
next_certificate
Show source codeHide source code
fn pub mut next_certificate -> Result[Option[Certificate], ParseError[E]] {
loop {
match parse {
case Ok(Some(Certificate(v))) -> return Result.Ok(Option.Some(v))
case Ok(Some(_)) -> {}
case Error(e) -> throw e
case _ -> return Result.Ok(Option.None)
}
}
}fn pub mut next_certificate -> Result[Option[Certificate], ParseError[E]]Returns the next certificate found in the PEM file.
Examples
import std.crypto.pem (PemFile)
import std.io (Buffer)
let input = '
-----BEGIN CERTIFICATE-----
aGVsbG8=
-----END CERTIFICATE-----
'
let pem = PemFile.new(Buffer.new(input))
pem.next_certificate # => Result.Ok(Option.Some(Certificate(...)))
next_private_key
Show source codeHide source code
fn pub mut next_private_key -> Result[Option[PrivateKey], ParseError[E]] {
loop {
match parse {
case Ok(Some(PrivateKey(v))) -> return Result.Ok(Option.Some(v))
case Ok(Some(_)) -> {}
case Error(e) -> throw e
case _ -> return Result.Ok(Option.None)
}
}
}fn pub mut next_private_key -> Result[Option[PrivateKey], ParseError[E]]Returns the next private key found in the PEM file.
Examples
import std.crypto.pem (PemFile)
import std.io (Buffer)
let input = '
-----BEGIN PRIVATE KEY-----
aGVsbG8=
-----END PRIVATE KEY-----
'
let pem = PemFile.new(Buffer.new(input))
pem.next_private_key # => Result.Ok(Option.Some(PrivateKey(...)))
partition
Show source codeHide source code
fn pub move partition(func: fn (ref T) -> Bool) -> (Array[T], Array[T]) {
reduce(([], []), fn move (acc, val) {
if func.call(ref val) { acc.0.push(val) } else { acc.1.push(val) }
acc
})
}fn pub move partition(func: fn (ref T) -> Bool) -> (Array[T], Array[T])Partitions the Iter into a tuple of two Array objects.
The first value of the tuple contains all values for which the supplied
func returned true. The second value contains all values for which the
func returned false.
Examples
Partitioning an Iter:
let values = [10, 20, 30, 40, 50]
let pair = values.iter.partition fn (value) { value >= 30 }
pair.0 # => [30, 40, 50]
pair.1 # => [10, 20]
peekable
Show source codeHide source code
fn pub move peekable -> Peekable[T, Self] {
Peekable(iter: self, peeked: Option.None)
}fn pub move peekable -> Peekable[T, Self]Returns an iterator that allows looking at the next element of the iterator, without consuming it.
Examples
let vals = [1, 2, 3]
let iter = vals.iter.peekable
iter.peek # => Option.Some(1)
iter.peek # => Option.Some(1)
iter.next # => Option.Some(1)
iter.next # => Option.Some(2)
reduce
Show source codeHide source code
fn pub move reduce[A](accumulator: A, func: fn (A, T) -> A) -> A {
let mut result = accumulator
loop {
match self.next {
case Some(v) -> result = func.call(result, v)
case _ -> return result
}
}
}fn pub move reduce[A](accumulator: A, func: fn (A, T) -> A) -> ACombines all values in the iterator into the specified accumulator.
This method takes two arguments:
- An accumulator to combine all values into.
2. A func that accepts two arguments: the accumulator and the current value.
The func returns the accumulator to return for the next value. The return value of this method is the final accumulator.
This method is called inject or fold in other languages.
Examples
Summing all integers in an iterator:
let total = [1, 2, 3].iter.reduce(0) fn (total, current) {
total + current
}
total # => 6
At each step of the iteration, the total and current func arguments are
set to the following values:
| Element | Total | Current | Return value |
|---|---|---|---|
| 0 | 0 | 1 | 1 |
| 1 | 1 | 2 | 3 |
| 2 | 3 | 3 | 6 |
For the last element the return value is 6, so the return value of the
reduce method is also 6.
select
Show source codeHide source code
fn pub move select(func: fn (ref T) -> Bool) -> Stream[T] {
Stream.new(fn move {
loop {
match self.next {
case Some(v) -> if func.call(v) { return Option.Some(v) }
case _ -> return Option.None
}
}
})
}fn pub move select(func: fn (ref T) -> Bool) -> Stream[T]Returns an Iter that only produces values for which the supplied func
returned true.
Examples
Selecting only certain values in an Iter:
[10, 20, 30]
.iter
.select fn (value) { value > 10 }
.to_array # => [20, 30]
select_map
Show source codeHide source code
fn pub move select_map[R](func: fn (T) -> Option[R]) -> Stream[R] {
Stream.new(fn move {
loop {
match self.next {
case Some(v) -> {
match func.call(v) {
case Some(r) -> return Option.Some(r)
case _ -> next
}
}
case _ -> return Option.None
}
}
})
}fn pub move select_map[R](func: fn (T) -> Option[R]) -> Stream[R]Returns an Iter that both filters and maps at the same time.
The new iterator yields the values for which the provided func returned a
Some value.
Examples
let vals = [Option.Some(10), Option.None, Option.som(30)]
let iter = vals.into_iter.select_map fn (opt) { opt }
iter.next # => Option.Some(10)
iter.next # => Option.Some(30)
iter.next # => Option.None
skip
Show source codeHide source code
fn pub move skip(amount: Int) -> Stream[T] {
let mut pending = amount
Stream.new(fn move {
while pending > 0 {
match self.next {
case Some(_) -> pending -= 1
case _ -> break
}
}
self.next
})
}fn pub move skip(amount: Int) -> Stream[T]Returns a new iterator that skips the first amount values yielded, then
yields any remaining values.
The first time next is called on the returned iterator, the iterator is
advanced amount times. The new iterator yields a None if there are fewer
than amount items in the iterator.
Examples
[1, 2, 3].into_iter.skip(1).to_array # => [2, 3]
[1].into_iter.skip(10).to_array # => []
skip_while
Show source codeHide source code
fn pub move skip_while(func: fn (ref T) -> Bool) -> Stream[T] {
let mut skip = true
Stream.new(fn move {
while skip {
match self.next {
case Some(v) if func.call(v) -> {}
case Some(v) -> {
skip = false
return Option.Some(v)
}
case _ -> return Option.None
}
}
self.next
})
}fn pub move skip_while(func: fn (ref T) -> Bool) -> Stream[T]Returns a new iterator that skips values for which func returns true.
Once func returns false, the remaining values in the iterator are
yielded, and func is no longer called.
Examples
[1, 2, 3].into_iter.skip_while fn (v) { v <= 2 }.to_array # => [3]
take
Show source codeHide source code
fn pub move take(amount: Int) -> Stream[T] {
let mut pending = amount
Stream.new(fn move {
if (pending := pending - 1) > 0 { self.next } else { Option.None }
})
}fn pub move take(amount: Int) -> Stream[T]Returns a new iterator that yields the first amount items, or fewer if
amount is greater than the number of values in the iterator.
Examples
[1, 2, 3].into_iter.take(2).to_array # => [1, 2]
[1].into_iter.take(2).to_array # => [1]
take_while
Show source codeHide source code
fn pub move take_while(func: fn (ref T) -> Bool) -> Stream[T] {
let mut take = true
Stream.new(fn move {
if take {
match self.next {
case Some(v) if func.call(v) -> Option.Some(v)
case Some(_) -> {
take = false
Option.None
}
case _ -> Option.None
}
} else {
Option.None
}
})
}fn pub move take_while(func: fn (ref T) -> Bool) -> Stream[T]Returns a new iterator that yields values for which func returns true.
When func returns false, any remaining values in the iterator are
ignored and the iterator is no longer advanced.
Examples
[1, 2, 3].into_iter.take_while fn (v) { v <= 2 }.to_array # => [1, 2]
to_array
Show source codeHide source code
fn pub move to_array -> Array[T] {
reduce([], fn (values, value) {
values.push(value)
values
})
}fn pub move to_array -> Array[T]Collects all values in the Iter in an Array.
This method will advance the iterator to the end.
Examples
Transforming an Iter back into an Array:
[1, 2, 3].iter.to_array # => [1, 2, 3]
try_reduce
Show source codeHide source code
fn pub mut try_reduce[A, E](
accumulator: A,
func: fn (A, T) -> Result[A, E],
) -> Result[A, E] {
let mut result = accumulator
loop {
match self.next {
case Some(v) -> result = try func.call(result, v)
case _ -> return Result.Ok(result)
}
}
}fn pub mut try_reduce[A, E](accumulator: A, func: fn (A, T) -> Result[A, E]) -> Result[A, E]Combines all values in the iterator into the specified accumulator, stopping
at the first Error that is encountered.
This method is similar to Iter.reduce, except the given closure is
expected to return a Result wrapping the accumulator. If the return value
is an Ok, iteration continues. If the return value is an Error,
iteration stops and the Error is returned.
Examples
let iter = [Result.Ok(1), Result.Error('test'), Result.Ok(2)].into_iter
let result = iter.try_reduce(0) fn (acc, val) {
match val {
case Ok(val) -> Result.Ok(acc + val)
case err -> err
}
}
result # => Result.Error('test')
with_index
Show source codeHide source code
fn pub move with_index -> Stream[(Int, T)] {
let mut index = 0
map(fn move (val) { (index := index + 1, val) })
}fn pub move with_index -> Stream[(Int, T)]Returns an Iter that yields a tuple of the index and the iterator value.
Examples
let iter = [10, 20].into_iter.with_index
iter.next # => Option.Some((0, 10))
iter.next # => Option.Some((1, 20))
zip
Show source codeHide source code
fn pub move zip[U, I: mut + Iter[U]](other: I) -> Stream[(T, U)] {
Stream.new(fn move { self.next.zip(other.next) })
}fn pub move zip[U, I: mut + Iter[U]](other: I: mut) -> Stream[(T, U)]Zips two Iter objects together, producing a new Iter that produces a
tuple containing the values of both Iter objects.
The returned Iter stops iterating when one of the two zipped Iter
objects runs out of values.
Examples
Zipping two Iter objects together:
let a = [10, 20, 30]
let b = [40, 50, 60]
let zip = a.iter.zip(b.iter)
zip.next # => (10, 40)
Zipping two Iter objects with a different number of values:
let a = [10, 20, 30]
let b = [40, 50]
let zip = a.iter.zip(b.iter)
zip.next # => (10, 40)
Implemented traits
Iter
impl Iter[Result[Item, ParseError[E]]] for PemFile