all: change optional to result in most of the libraries (#16123)

This commit is contained in:
yuyi 2022-10-21 03:14:33 +08:00 committed by GitHub
parent 0d368562f4
commit 51f4d99399
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
75 changed files with 439 additions and 446 deletions

View file

@ -81,16 +81,16 @@ jobs:
echo "Test libsodium" echo "Test libsodium"
VJOBS=1 v test ~/.vmodules/libsodium VJOBS=1 v test ~/.vmodules/libsodium
- name: Build VEX ## - name: Build VEX
run: | ## run: |
echo "Install Vex" ## echo "Install Vex"
v install nedpals.vex ## v install nedpals.vex
echo "Compile all of the Vex examples" ## echo "Compile all of the Vex examples"
v should-compile-all ~/.vmodules/nedpals/vex/examples ## v should-compile-all ~/.vmodules/nedpals/vex/examples
echo "Compile the simple Vex example with -gc boehm -skip-unused" ## echo "Compile the simple Vex example with -gc boehm -skip-unused"
v -gc boehm -skip-unused ~/.vmodules/nedpals/vex/examples/simple_example.v ## v -gc boehm -skip-unused ~/.vmodules/nedpals/vex/examples/simple_example.v
echo "Run Vex Tests" ## echo "Run Vex Tests"
v test ~/.vmodules/nedpals/vex ## v test ~/.vmodules/nedpals/vex
- name: Build go2v - name: Build go2v
run: | run: |

View file

@ -16,7 +16,7 @@ fn find_diff_cmd() string {
fn test_vet() { fn test_vet() {
os.setenv('VCOLORS', 'never', true) os.setenv('VCOLORS', 'never', true)
os.chdir(vroot)? os.chdir(vroot)!
test_dir := 'cmd/tools/vdoc/tests/testdata' test_dir := 'cmd/tools/vdoc/tests/testdata'
main_files := get_main_files_in_dir(test_dir) main_files := get_main_files_in_dir(test_dir)
fails := check_path(vexe, test_dir, main_files) fails := check_path(vexe, test_dir, main_files)

View file

@ -70,7 +70,7 @@ fn set_output_type_from_str(format string) OutputType {
return output_type return output_type
} }
fn get_ignore_paths(path string) ?[]string { fn get_ignore_paths(path string) ![]string {
ignore_file_path := os.join_path(path, '.vdocignore') ignore_file_path := os.join_path(path, '.vdocignore')
ignore_content := os.read_file(ignore_file_path) or { ignore_content := os.read_file(ignore_file_path) or {
return error_with_code('ignore file not found.', 1) return error_with_code('ignore file not found.', 1)

View file

@ -41,7 +41,7 @@ fn main() {
cmd.parse(os.args) cmd.parse(os.args)
} }
fn greet_func(cmd Command) ? { fn greet_func(cmd Command) ! {
language := cmd.flags.get_string('language') or { panic('Failed to get `language` flag: $err') } language := cmd.flags.get_string('language') or { panic('Failed to get `language` flag: $err') }
times := cmd.flags.get_int('times') or { panic('Failed to get `times` flag: $err') } times := cmd.flags.get_int('times') or { panic('Failed to get `times` flag: $err') }
name := cmd.args[0] name := cmd.args[0]
@ -69,10 +69,10 @@ fn greet_func(cmd Command) ? {
} }
} }
fn greet_pre_func(cmd Command) ? { fn greet_pre_func(cmd Command) ! {
println('This is a function running before the main function.\n') println('This is a function running before the main function.\n')
} }
fn greet_post_func(cmd Command) ? { fn greet_post_func(cmd Command) ! {
println('\nThis is a function running after the main function.') println('\nThis is a function running after the main function.')
} }

View file

@ -10,7 +10,7 @@ fn main() {
for _ in 0 .. repeats { for _ in 0 .. repeats {
mut sb := strings.new_builder(blocksize) mut sb := strings.new_builder(blocksize)
for { for {
x := rand.read(blocksize)? x := rand.read(blocksize)!
for c in x { for c in x {
if c >= `0` && c <= `~` { if c >= `0` && c <= `~` {
sb.write_u8(c) sb.write_u8(c)

View file

@ -9,8 +9,8 @@ import arrays
fn main() { fn main() {
a := [1, 5, 7, 0, 9] a := [1, 5, 7, 0, 9]
assert arrays.min(a)? == 0 assert arrays.min(a)! == 0
assert arrays.max(a)? == 9 assert arrays.max(a)! == 9
assert arrays.idx_min(a)? == 3 assert arrays.idx_min(a)! == 3
} }
``` ```

View file

@ -200,7 +200,7 @@ pub fn window<T>(array []T, attr WindowAttribute) [][]T {
// which means you can only pass array of numbers for now. // which means you can only pass array of numbers for now.
// TODO: Fix generic operator overloading detection issue. // TODO: Fix generic operator overloading detection issue.
// Example: arrays.sum<int>([1, 2, 3, 4, 5])? // => 15 // Example: arrays.sum<int>([1, 2, 3, 4, 5])? // => 15
pub fn sum<T>(array []T) ?T { pub fn sum<T>(array []T) !T {
if array.len == 0 { if array.len == 0 {
return error('Cannot sum up array of nothing.') return error('Cannot sum up array of nothing.')
} else { } else {
@ -222,8 +222,8 @@ pub fn sum<T>(array []T) ?T {
// returns the accumulated value in `acc`. // returns the accumulated value in `acc`.
// returns an error if the array is empty. // returns an error if the array is empty.
// See also: [fold](#fold). // See also: [fold](#fold).
// Example: arrays.reduce([1, 2, 3, 4, 5], fn (t1 int, t2 int) int { return t1 * t2 })? // => 120 // Example: arrays.reduce([1, 2, 3, 4, 5], fn (t1 int, t2 int) int { return t1 * t2 })! // => 120
pub fn reduce<T>(array []T, reduce_op fn (acc T, elem T) T) ?T { pub fn reduce<T>(array []T, reduce_op fn (acc T, elem T) T) !T {
if array.len == 0 { if array.len == 0 {
return error('Cannot reduce array of nothing.') return error('Cannot reduce array of nothing.')
} else { } else {
@ -245,7 +245,7 @@ pub fn reduce<T>(array []T, reduce_op fn (acc T, elem T) T) ?T {
// returns the accumulated value in `acc`. // returns the accumulated value in `acc`.
// returns an error if the array is empty. // returns an error if the array is empty.
// See also: [fold_indexed](#fold_indexed). // See also: [fold_indexed](#fold_indexed).
pub fn reduce_indexed<T>(array []T, reduce_op fn (idx int, acc T, elem T) T) ?T { pub fn reduce_indexed<T>(array []T, reduce_op fn (idx int, acc T, elem T) T) !T {
if array.len == 0 { if array.len == 0 {
return error('Cannot reduce array of nothing.') return error('Cannot reduce array of nothing.')
} else { } else {
@ -427,8 +427,8 @@ pub fn lower_bound<T>(array []T, val T) !T {
} }
// returns the largest element <= val, requires `array` to be sorted // returns the largest element <= val, requires `array` to be sorted
// Example: arrays.upper_bound([2, 4, 6, 8], 3)? // => 2 // Example: arrays.upper_bound([2, 4, 6, 8], 3)! // => 2
pub fn upper_bound<T>(array []T, val T) ?T { pub fn upper_bound<T>(array []T, val T) !T {
if array.len == 0 { if array.len == 0 {
return error('.upper_bound called on an empty array') return error('.upper_bound called on an empty array')
} }

View file

@ -14,7 +14,7 @@ fn test_min() {
c := [u8(4), 9, 3, 1] c := [u8(4), 9, 3, 1]
mut rb := min(c)! mut rb := min(c)!
assert rb == u8(1) assert rb == u8(1)
rb = min(c[..3])? rb = min(c[..3])!
assert rb == u8(3) assert rb == u8(3)
} }
@ -243,7 +243,7 @@ fn test_concat_string() {
fn test_binary_search() { fn test_binary_search() {
a := [1, 3, 3, 4, 5, 6, 7, 8, 10] a := [1, 3, 3, 4, 5, 6, 7, 8, 10]
assert binary_search(a, 3)? == 1 assert binary_search(a, 3)! == 1
assert (binary_search(a, 0) or { -1 }) == -1 assert (binary_search(a, 0) or { -1 }) == -1
} }
@ -251,18 +251,18 @@ fn test_lower_bound() {
a := [1, 3, 3, 4, 5, 6, 7, 8, 10] a := [1, 3, 3, 4, 5, 6, 7, 8, 10]
b := []int{} b := []int{}
c := [1, 2, 3] c := [1, 2, 3]
assert lower_bound(a, 2)? == 3 assert lower_bound(a, 2)! == 3
assert (lower_bound(b, 4) or { -1 }) == -1 assert (lower_bound(b, 4) or { -1 }) == -1
assert lower_bound(c, 3)? == 3 assert lower_bound(c, 3)! == 3
} }
fn test_upper_bound() { fn test_upper_bound() {
a := [1, 3, 3, 4, 5, 6, 7, 8, 10] a := [1, 3, 3, 4, 5, 6, 7, 8, 10]
b := []int{} b := []int{}
c := [1, 2, 3] c := [1, 2, 3]
assert upper_bound(a, 9)? == 8 assert upper_bound(a, 9)! == 8
assert (upper_bound(b, 4) or { -1 }) == -1 assert (upper_bound(b, 4) or { -1 }) == -1
assert upper_bound(c, 2)? == 2 assert upper_bound(c, 2)! == 2
} }
fn test_rotate_right() { fn test_rotate_right() {

View file

@ -18,14 +18,14 @@ fn main() {
mut app := cli.Command{ mut app := cli.Command{
name: 'example-app' name: 'example-app'
description: 'example-app' description: 'example-app'
execute: fn (cmd cli.Command) ? { execute: fn (cmd cli.Command) ! {
println('hello app') println('hello app')
return return
} }
commands: [ commands: [
cli.Command{ cli.Command{
name: 'sub' name: 'sub'
execute: fn (cmd cli.Command) ? { execute: fn (cmd cli.Command) ! {
println('hello subcommand') println('hello subcommand')
return return
} }

View file

@ -2,7 +2,7 @@ module cli
import term import term
type FnCommandCallback = fn (cmd Command) ? type FnCommandCallback = fn (cmd Command) !
// str returns the `string` representation of the callback. // str returns the `string` representation of the callback.
pub fn (f FnCommandCallback) str() string { pub fn (f FnCommandCallback) str() string {
@ -311,7 +311,7 @@ pub fn (cmd Command) execute_man() {
} }
} }
fn (cmds []Command) get(name string) ?Command { fn (cmds []Command) get(name string) !Command {
for cmd in cmds { for cmd in cmds {
if cmd.name == name { if cmd.name == name {
return cmd return cmd

View file

@ -30,7 +30,7 @@ fn test_if_subcommands_parse_args() {
cmd.parse(['command', 'subcommand', 'arg0', 'arg1']) cmd.parse(['command', 'subcommand', 'arg0', 'arg1'])
} }
fn if_subcommands_parse_args_func(cmd cli.Command) ? { fn if_subcommands_parse_args_func(cmd cli.Command) ! {
assert cmd.name == 'subcommand' && compare_arrays(cmd.args, ['arg0', 'arg1']) assert cmd.name == 'subcommand' && compare_arrays(cmd.args, ['arg0', 'arg1'])
} }
@ -51,8 +51,8 @@ fn test_if_command_has_default_version_subcommand_if_version_is_set() {
assert has_command(cmd, 'version') assert has_command(cmd, 'version')
} }
fn flag_should_be_set(cmd cli.Command) ? { fn flag_should_be_set(cmd cli.Command) ! {
flag := cmd.flags.get_string('flag')? flag := cmd.flags.get_string('flag')!
assert flag == 'value' assert flag == 'value'
} }
@ -95,10 +95,10 @@ fn test_if_flag_gets_set_with_long_arg() {
cmd.parse(['command', '--flag', 'value']) cmd.parse(['command', '--flag', 'value'])
} }
fn flag_should_have_value_of_42(cmd cli.Command) ? { fn flag_should_have_value_of_42(cmd cli.Command) ! {
flag := cmd.flags.get_string('flag')? flag := cmd.flags.get_string('flag')!
assert flag == 'value' assert flag == 'value'
value := cmd.flags.get_int('value')? value := cmd.flags.get_int('value')!
assert value == 42 assert value == 42
} }
@ -135,7 +135,7 @@ fn test_if_required_flags_get_set() {
cmd.parse(['command', '-flag', 'value', '-value', '42']) cmd.parse(['command', '-flag', 'value', '-value', '42'])
} }
fn flag_is_set_in_subcommand(cmd cli.Command) ? { fn flag_is_set_in_subcommand(cmd cli.Command) ! {
flag := cmd.flags.get_string('flag') or { panic(err) } flag := cmd.flags.get_string('flag') or { panic(err) }
assert flag == 'value' assert flag == 'value'
} }
@ -197,7 +197,7 @@ fn test_command_setup() {
} }
// helper functions // helper functions
fn empty_func(cmd cli.Command) ? { fn empty_func(cmd cli.Command) ! {
} }
fn has_command(cmd cli.Command, name string) bool { fn has_command(cmd cli.Command, name string) bool {

View file

@ -42,7 +42,7 @@ pub fn (flags []Flag) get_all_found() []Flag {
// get_bool returns `true` if the flag is set. // get_bool returns `true` if the flag is set.
// get_bool returns an error if the `FlagType` is not boolean. // get_bool returns an error if the `FlagType` is not boolean.
pub fn (flag Flag) get_bool() ?bool { pub fn (flag Flag) get_bool() !bool {
if flag.flag != .bool { if flag.flag != .bool {
return error('$flag.name: Invalid flag type `$flag.flag`, expected `bool`') return error('$flag.name: Invalid flag type `$flag.flag`, expected `bool`')
} }
@ -54,14 +54,14 @@ pub fn (flag Flag) get_bool() ?bool {
// get_bool returns `true` if the flag specified in `name` is set. // get_bool returns `true` if the flag specified in `name` is set.
// get_bool returns an error if the `FlagType` is not boolean. // get_bool returns an error if the `FlagType` is not boolean.
pub fn (flags []Flag) get_bool(name string) ?bool { pub fn (flags []Flag) get_bool(name string) !bool {
flag := flags.get(name)? flag := flags.get(name)!
return flag.get_bool() return flag.get_bool()
} }
// get_int returns the `int` value argument of the flag. // get_int returns the `int` value argument of the flag.
// get_int returns an error if the `FlagType` is not integer. // get_int returns an error if the `FlagType` is not integer.
pub fn (flag Flag) get_int() ?int { pub fn (flag Flag) get_int() !int {
if flag.flag != .int { if flag.flag != .int {
return error('$flag.name: Invalid flag type `$flag.flag`, expected `int`') return error('$flag.name: Invalid flag type `$flag.flag`, expected `int`')
} }
@ -77,7 +77,7 @@ pub fn (flag Flag) get_int() ?int {
// get_ints returns the array of `int` value argument of the flag specified in `name`. // get_ints returns the array of `int` value argument of the flag specified in `name`.
// get_ints returns an error if the `FlagType` is not integer. // get_ints returns an error if the `FlagType` is not integer.
pub fn (flag Flag) get_ints() ?[]int { pub fn (flag Flag) get_ints() ![]int {
if flag.flag != .int_array { if flag.flag != .int_array {
return error('$flag.name: Invalid flag type `$flag.flag`, expected `int_array`') return error('$flag.name: Invalid flag type `$flag.flag`, expected `int_array`')
} }
@ -99,21 +99,21 @@ pub fn (flag Flag) get_ints() ?[]int {
// get_int returns the `int` value argument of the flag specified in `name`. // get_int returns the `int` value argument of the flag specified in `name`.
// get_int returns an error if the `FlagType` is not integer. // get_int returns an error if the `FlagType` is not integer.
pub fn (flags []Flag) get_int(name string) ?int { pub fn (flags []Flag) get_int(name string) !int {
flag := flags.get(name)? flag := flags.get(name)!
return flag.get_int() return flag.get_int()
} }
// get_ints returns the array of `int` value argument of the flag specified in `name`. // get_ints returns the array of `int` value argument of the flag specified in `name`.
// get_ints returns an error if the `FlagType` is not integer. // get_ints returns an error if the `FlagType` is not integer.
pub fn (flags []Flag) get_ints(name string) ?[]int { pub fn (flags []Flag) get_ints(name string) ![]int {
flag := flags.get(name)? flag := flags.get(name)!
return flag.get_ints() return flag.get_ints()
} }
// get_float returns the `f64` value argument of the flag. // get_float returns the `f64` value argument of the flag.
// get_float returns an error if the `FlagType` is not floating point. // get_float returns an error if the `FlagType` is not floating point.
pub fn (flag Flag) get_float() ?f64 { pub fn (flag Flag) get_float() !f64 {
if flag.flag != .float { if flag.flag != .float {
return error('$flag.name: Invalid flag type `$flag.flag`, expected `float`') return error('$flag.name: Invalid flag type `$flag.flag`, expected `float`')
} }
@ -129,7 +129,7 @@ pub fn (flag Flag) get_float() ?f64 {
// get_floats returns the `f64` value argument of the flag. // get_floats returns the `f64` value argument of the flag.
// get_floats returns an error if the `FlagType` is not floating point. // get_floats returns an error if the `FlagType` is not floating point.
pub fn (flag Flag) get_floats() ?[]f64 { pub fn (flag Flag) get_floats() ![]f64 {
if flag.flag != .float_array { if flag.flag != .float_array {
return error('$flag.name: Invalid flag type `$flag.flag`, expected `float_array`') return error('$flag.name: Invalid flag type `$flag.flag`, expected `float_array`')
} }
@ -151,21 +151,21 @@ pub fn (flag Flag) get_floats() ?[]f64 {
// get_float returns the `f64` value argument of the flag specified in `name`. // get_float returns the `f64` value argument of the flag specified in `name`.
// get_float returns an error if the `FlagType` is not floating point. // get_float returns an error if the `FlagType` is not floating point.
pub fn (flags []Flag) get_float(name string) ?f64 { pub fn (flags []Flag) get_float(name string) !f64 {
flag := flags.get(name)? flag := flags.get(name)!
return flag.get_float() return flag.get_float()
} }
// get_floats returns the array of `f64` value argument of the flag specified in `name`. // get_floats returns the array of `f64` value argument of the flag specified in `name`.
// get_floats returns an error if the `FlagType` is not floating point. // get_floats returns an error if the `FlagType` is not floating point.
pub fn (flags []Flag) get_floats(name string) ?[]f64 { pub fn (flags []Flag) get_floats(name string) ![]f64 {
flag := flags.get(name)? flag := flags.get(name)!
return flag.get_floats() return flag.get_floats()
} }
// get_string returns the `string` value argument of the flag. // get_string returns the `string` value argument of the flag.
// get_string returns an error if the `FlagType` is not string. // get_string returns an error if the `FlagType` is not string.
pub fn (flag Flag) get_string() ?string { pub fn (flag Flag) get_string() !string {
if flag.flag != .string { if flag.flag != .string {
return error('$flag.name: Invalid flag type `$flag.flag`, expected `string`') return error('$flag.name: Invalid flag type `$flag.flag`, expected `string`')
} }
@ -181,7 +181,7 @@ pub fn (flag Flag) get_string() ?string {
// get_strings returns the array of `string` value argument of the flag. // get_strings returns the array of `string` value argument of the flag.
// get_strings returns an error if the `FlagType` is not string. // get_strings returns an error if the `FlagType` is not string.
pub fn (flag Flag) get_strings() ?[]string { pub fn (flag Flag) get_strings() ![]string {
if flag.flag != .string_array { if flag.flag != .string_array {
return error('$flag.name: Invalid flag type `$flag.flag`, expected `string_array`') return error('$flag.name: Invalid flag type `$flag.flag`, expected `string_array`')
} }
@ -197,24 +197,24 @@ pub fn (flag Flag) get_strings() ?[]string {
// get_string returns the `string` value argument of the flag specified in `name`. // get_string returns the `string` value argument of the flag specified in `name`.
// get_string returns an error if the `FlagType` is not string. // get_string returns an error if the `FlagType` is not string.
pub fn (flags []Flag) get_string(name string) ?string { pub fn (flags []Flag) get_string(name string) !string {
flag := flags.get(name)? flag := flags.get(name)!
return flag.get_string() return flag.get_string()
} }
// get_strings returns the `string` value argument of the flag specified in `name`. // get_strings returns the `string` value argument of the flag specified in `name`.
// get_strings returns an error if the `FlagType` is not string. // get_strings returns an error if the `FlagType` is not string.
pub fn (flags []Flag) get_strings(name string) ?[]string { pub fn (flags []Flag) get_strings(name string) ![]string {
flag := flags.get(name)? flag := flags.get(name)!
return flag.get_strings() return flag.get_strings()
} }
// parse parses flag values from arguments and return // parse parses flag values from arguments and return
// an array of arguments with all consumed elements removed. // an array of arguments with all consumed elements removed.
fn (mut flag Flag) parse(args []string, posix_mode bool) ?[]string { fn (mut flag Flag) parse(args []string, posix_mode bool) ![]string {
if flag.matches(args, posix_mode) { if flag.matches(args, posix_mode) {
if flag.flag == .bool { if flag.flag == .bool {
new_args := flag.parse_bool(args)? new_args := flag.parse_bool(args)!
return new_args return new_args
} else { } else {
if flag.value.len > 0 && flag.flag != .int_array && flag.flag != .float_array if flag.value.len > 0 && flag.flag != .int_array && flag.flag != .float_array
@ -222,7 +222,7 @@ fn (mut flag Flag) parse(args []string, posix_mode bool) ?[]string {
return error('The argument `$flag.name` accept only one value!') return error('The argument `$flag.name` accept only one value!')
} }
new_args := flag.parse_raw(args)? new_args := flag.parse_raw(args)!
return new_args return new_args
} }
} else { } else {
@ -239,7 +239,7 @@ fn (mut flag Flag) matches(args []string, posix_mode bool) bool {
|| (flag.abbrev != '' && args[0].starts_with('-$flag.abbrev=')) || (flag.abbrev != '' && args[0].starts_with('-$flag.abbrev='))
} }
fn (mut flag Flag) parse_raw(args []string) ?[]string { fn (mut flag Flag) parse_raw(args []string) ![]string {
if args[0].len > flag.name.len && args[0].contains('=') { if args[0].len > flag.name.len && args[0].contains('=') {
flag.value << args[0].split('=')[1] flag.value << args[0].split('=')[1]
return args[1..] return args[1..]
@ -250,7 +250,7 @@ fn (mut flag Flag) parse_raw(args []string) ?[]string {
return error('Missing argument for `$flag.name`') return error('Missing argument for `$flag.name`')
} }
fn (mut flag Flag) parse_bool(args []string) ?[]string { fn (mut flag Flag) parse_bool(args []string) ![]string {
if args[0].len > flag.name.len && args[0].contains('=') { if args[0].len > flag.name.len && args[0].contains('=') {
flag.value = [args[0].split('=')[1]] flag.value = [args[0].split('=')[1]]
return args[1..] return args[1..]
@ -267,7 +267,7 @@ fn (mut flag Flag) parse_bool(args []string) ?[]string {
// get returns the `Flag` matching `name` or an error // get returns the `Flag` matching `name` or an error
// if it can't be found. // if it can't be found.
fn (flags []Flag) get(name string) ?Flag { fn (flags []Flag) get(name string) !Flag {
for flag in flags { for flag in flags {
if flag.name == name { if flag.name == name {
return flag return flag

View file

@ -29,7 +29,7 @@ fn help_cmd() Command {
} }
// print_help_for_command outputs the help message of `help_cmd`. // print_help_for_command outputs the help message of `help_cmd`.
pub fn print_help_for_command(help_cmd Command) ? { pub fn print_help_for_command(help_cmd Command) ! {
if help_cmd.args.len > 0 { if help_cmd.args.len > 0 {
mut cmd := help_cmd.parent mut cmd := help_cmd.parent
for arg in help_cmd.args { for arg in help_cmd.args {

View file

@ -21,7 +21,7 @@ fn man_cmd() Command {
// print_manpage_for_command prints the manpage for the // print_manpage_for_command prints the manpage for the
// command or subcommand in `man_cmd` to stdout // command or subcommand in `man_cmd` to stdout
pub fn print_manpage_for_command(man_cmd Command) ? { pub fn print_manpage_for_command(man_cmd Command) ! {
if man_cmd.args.len > 0 { if man_cmd.args.len > 0 {
mut cmd := man_cmd.parent mut cmd := man_cmd.parent
for arg in man_cmd.args { for arg in man_cmd.args {

View file

@ -18,7 +18,7 @@ fn version_cmd() Command {
} }
} }
fn version_func(version_cmd Command) ? { fn version_func(version_cmd Command) ! {
cmd := version_cmd.parent cmd := version_cmd.parent
version := '$cmd.name version $cmd.version' version := '$cmd.name version $cmd.version'
println(version) println(version)

View file

@ -11,7 +11,7 @@ fn C.tinfl_decompress_mem_to_heap(source_buf voidptr, source_buf_len usize, out_
// compresses an array of bytes based on providing flags and returns the compressed bytes in a new array // compresses an array of bytes based on providing flags and returns the compressed bytes in a new array
// NB: this is a low level api, a high level implementation like zlib/gzip should be preferred // NB: this is a low level api, a high level implementation like zlib/gzip should be preferred
[manualfree] [manualfree]
pub fn compress(data []u8, flags int) ?[]u8 { pub fn compress(data []u8, flags int) ![]u8 {
if u64(data.len) > compress.max_size { if u64(data.len) > compress.max_size {
return error('data too large ($data.len > $compress.max_size)') return error('data too large ($data.len > $compress.max_size)')
} }
@ -30,7 +30,7 @@ pub fn compress(data []u8, flags int) ?[]u8 {
// decompresses an array of bytes based on providing flags and returns the decompressed bytes in a new array // decompresses an array of bytes based on providing flags and returns the decompressed bytes in a new array
// NB: this is a low level api, a high level implementation like zlib/gzip should be preferred // NB: this is a low level api, a high level implementation like zlib/gzip should be preferred
[manualfree] [manualfree]
pub fn decompress(data []u8, flags int) ?[]u8 { pub fn decompress(data []u8, flags int) ![]u8 {
mut out_len := usize(0) mut out_len := usize(0)
address := C.tinfl_decompress_mem_to_heap(data.data, data.len, &out_len, flags) address := C.tinfl_decompress_mem_to_heap(data.data, data.len, &out_len, flags)

View file

@ -11,8 +11,8 @@ import compress.deflate
fn main() { fn main() {
uncompressed := 'Hello world!' uncompressed := 'Hello world!'
compressed := deflate.compress(uncompressed.bytes())? compressed := deflate.compress(uncompressed.bytes())!
decompressed := deflate.decompress(compressed)? decompressed := deflate.decompress(compressed)!
assert decompressed == uncompressed.bytes() assert decompressed == uncompressed.bytes()
} }
``` ```

View file

@ -4,12 +4,12 @@ import compress
// compresses an array of bytes using deflate and returns the compressed bytes in a new array // compresses an array of bytes using deflate and returns the compressed bytes in a new array
// Example: compressed := deflate.compress(b)? // Example: compressed := deflate.compress(b)?
pub fn compress(data []u8) ?[]u8 { pub fn compress(data []u8) ![]u8 {
return compress.compress(data, 0) return compress.compress(data, 0)
} }
// decompresses an array of bytes using deflate and returns the decompressed bytes in a new array // decompresses an array of bytes using deflate and returns the decompressed bytes in a new array
// Example: decompressed := deflate.decompress(b)? // Example: decompressed := deflate.decompress(b)?
pub fn decompress(data []u8) ?[]u8 { pub fn decompress(data []u8) ![]u8 {
return compress.decompress(data, 0) return compress.decompress(data, 0)
} }

View file

@ -2,11 +2,11 @@ module deflate
const gzip_magic_numbers = [u8(0x1f), 0x8b] const gzip_magic_numbers = [u8(0x1f), 0x8b]
fn test_gzip() ? { fn test_gzip() {
uncompressed := 'Hello world!' uncompressed := 'Hello world!'
compressed := compress(uncompressed.bytes())? compressed := compress(uncompressed.bytes())!
first2 := compressed[0..2] first2 := compressed[0..2]
assert first2 != deflate.gzip_magic_numbers assert first2 != deflate.gzip_magic_numbers
decompressed := decompress(compressed)? decompressed := decompress(compressed)!
assert decompressed == uncompressed.bytes() assert decompressed == uncompressed.bytes()
} }

View file

@ -11,8 +11,8 @@ import compress.gzip
fn main() { fn main() {
uncompressed := 'Hello world!' uncompressed := 'Hello world!'
compressed := gzip.compress(uncompressed.bytes())? compressed := gzip.compress(uncompressed.bytes())!
decompressed := gzip.decompress(compressed)? decompressed := gzip.decompress(compressed)!
assert decompressed == uncompressed.bytes() assert decompressed == uncompressed.bytes()
} }
``` ```

View file

@ -8,8 +8,8 @@ import hash.crc32
// compresses an array of bytes using gzip and returns the compressed bytes in a new array // compresses an array of bytes using gzip and returns the compressed bytes in a new array
// Example: compressed := gzip.compress(b)? // Example: compressed := gzip.compress(b)?
pub fn compress(data []u8) ?[]u8 { pub fn compress(data []u8) ![]u8 {
compressed := compress.compress(data, 0)? compressed := compress.compress(data, 0)!
// header // header
mut result := [ mut result := [
u8(0x1f), // magic numbers (1F 8B) u8(0x1f), // magic numbers (1F 8B)
@ -49,7 +49,7 @@ pub struct DecompressParams {
// decompresses an array of bytes using zlib and returns the decompressed bytes in a new array // decompresses an array of bytes using zlib and returns the decompressed bytes in a new array
// Example: decompressed := gzip.decompress(b)? // Example: decompressed := gzip.decompress(b)?
pub fn decompress(data []u8, params DecompressParams) ?[]u8 { pub fn decompress(data []u8, params DecompressParams) ![]u8 {
if data.len < 18 { if data.len < 18 {
return error('data is too short, not gzip compressed?') return error('data is too short, not gzip compressed?')
} else if data[0] != 0x1f || data[1] != 0x8b { } else if data[0] != 0x1f || data[1] != 0x8b {
@ -107,7 +107,7 @@ pub fn decompress(data []u8, params DecompressParams) ?[]u8 {
return error('data too short') return error('data too short')
} }
decompressed := compress.decompress(data[header_length..data.len - 8], 0)? decompressed := compress.decompress(data[header_length..data.len - 8], 0)!
length_expected := (u32(data[data.len - 4]) << 24) | (u32(data[data.len - 3]) << 16) | (u32(data[data.len - 2]) << 8) | data[data.len - 1] length_expected := (u32(data[data.len - 4]) << 24) | (u32(data[data.len - 3]) << 16) | (u32(data[data.len - 2]) << 8) | data[data.len - 1]
if params.verify_length && decompressed.len != length_expected { if params.verify_length && decompressed.len != length_expected {
return error('length verification failed, got $decompressed.len, expected $length_expected') return error('length verification failed, got $decompressed.len, expected $length_expected')

View file

@ -2,14 +2,14 @@ module gzip
import hash.crc32 import hash.crc32
fn test_gzip() ? { fn test_gzip() {
uncompressed := 'Hello world!' uncompressed := 'Hello world!'
compressed := compress(uncompressed.bytes())? compressed := compress(uncompressed.bytes())!
decompressed := decompress(compressed)? decompressed := decompress(compressed)!
assert decompressed == uncompressed.bytes() assert decompressed == uncompressed.bytes()
} }
fn assert_decompress_error(data []u8, reason string) ? { fn assert_decompress_error(data []u8, reason string) ! {
decompress(data) or { decompress(data) or {
assert err.msg() == reason assert err.msg() == reason
return return
@ -17,54 +17,54 @@ fn assert_decompress_error(data []u8, reason string) ? {
return error('did not error') return error('did not error')
} }
fn test_gzip_invalid_too_short() ? { fn test_gzip_invalid_too_short() {
assert_decompress_error([]u8{}, 'data is too short, not gzip compressed?')? assert_decompress_error([]u8{}, 'data is too short, not gzip compressed?')!
} }
fn test_gzip_invalid_magic_numbers() ? { fn test_gzip_invalid_magic_numbers() {
assert_decompress_error([]u8{len: 100}, 'wrong magic numbers, not gzip compressed?')? assert_decompress_error([]u8{len: 100}, 'wrong magic numbers, not gzip compressed?')!
} }
fn test_gzip_invalid_compression() ? { fn test_gzip_invalid_compression() {
mut data := []u8{len: 100} mut data := []u8{len: 100}
data[0] = 0x1f data[0] = 0x1f
data[1] = 0x8b data[1] = 0x8b
assert_decompress_error(data, 'gzip data is not compressed with DEFLATE')? assert_decompress_error(data, 'gzip data is not compressed with DEFLATE')!
} }
fn test_gzip_with_ftext() ? { fn test_gzip_with_ftext() {
uncompressed := 'Hello world!' uncompressed := 'Hello world!'
mut compressed := compress(uncompressed.bytes())? mut compressed := compress(uncompressed.bytes())!
compressed[4] |= 0b0000_0001 // FTEXT compressed[4] |= 0b0000_0001 // FTEXT
decompressed := decompress(compressed)? decompressed := decompress(compressed)!
assert decompressed == uncompressed.bytes() assert decompressed == uncompressed.bytes()
} }
fn test_gzip_with_fname() ? { fn test_gzip_with_fname() {
uncompressed := 'Hello world!' uncompressed := 'Hello world!'
mut compressed := compress(uncompressed.bytes())? mut compressed := compress(uncompressed.bytes())!
compressed[4] |= 0b0000_1000 compressed[4] |= 0b0000_1000
compressed.insert(10, `h`) compressed.insert(10, `h`)
compressed.insert(11, `i`) compressed.insert(11, `i`)
compressed.insert(12, 0x00) compressed.insert(12, 0x00)
decompressed := decompress(compressed)? decompressed := decompress(compressed)!
assert decompressed == uncompressed.bytes() assert decompressed == uncompressed.bytes()
} }
fn test_gzip_with_fcomment() ? { fn test_gzip_with_fcomment() {
uncompressed := 'Hello world!' uncompressed := 'Hello world!'
mut compressed := compress(uncompressed.bytes())? mut compressed := compress(uncompressed.bytes())!
compressed[4] |= 0b0001_0000 compressed[4] |= 0b0001_0000
compressed.insert(10, `h`) compressed.insert(10, `h`)
compressed.insert(11, `i`) compressed.insert(11, `i`)
compressed.insert(12, 0x00) compressed.insert(12, 0x00)
decompressed := decompress(compressed)? decompressed := decompress(compressed)!
assert decompressed == uncompressed.bytes() assert decompressed == uncompressed.bytes()
} }
fn test_gzip_with_fname_fcomment() ? { fn test_gzip_with_fname_fcomment() {
uncompressed := 'Hello world!' uncompressed := 'Hello world!'
mut compressed := compress(uncompressed.bytes())? mut compressed := compress(uncompressed.bytes())!
compressed[4] |= 0b0001_1000 compressed[4] |= 0b0001_1000
compressed.insert(10, `h`) compressed.insert(10, `h`)
compressed.insert(11, `i`) compressed.insert(11, `i`)
@ -72,63 +72,63 @@ fn test_gzip_with_fname_fcomment() ? {
compressed.insert(10, `h`) compressed.insert(10, `h`)
compressed.insert(11, `i`) compressed.insert(11, `i`)
compressed.insert(12, 0x00) compressed.insert(12, 0x00)
decompressed := decompress(compressed)? decompressed := decompress(compressed)!
assert decompressed == uncompressed.bytes() assert decompressed == uncompressed.bytes()
} }
fn test_gzip_with_fextra() ? { fn test_gzip_with_fextra() {
uncompressed := 'Hello world!' uncompressed := 'Hello world!'
mut compressed := compress(uncompressed.bytes())? mut compressed := compress(uncompressed.bytes())!
compressed[4] |= 0b0000_0100 compressed[4] |= 0b0000_0100
compressed.insert(10, 2) compressed.insert(10, 2)
compressed.insert(11, `h`) compressed.insert(11, `h`)
compressed.insert(12, `i`) compressed.insert(12, `i`)
decompressed := decompress(compressed)? decompressed := decompress(compressed)!
assert decompressed == uncompressed.bytes() assert decompressed == uncompressed.bytes()
} }
fn test_gzip_with_hcrc() ? { fn test_gzip_with_hcrc() {
uncompressed := 'Hello world!' uncompressed := 'Hello world!'
mut compressed := compress(uncompressed.bytes())? mut compressed := compress(uncompressed.bytes())!
compressed[4] |= 0b0000_0010 compressed[4] |= 0b0000_0010
checksum := crc32.sum(compressed[..10]) checksum := crc32.sum(compressed[..10])
compressed.insert(10, u8(checksum >> 24)) compressed.insert(10, u8(checksum >> 24))
compressed.insert(11, u8(checksum >> 16)) compressed.insert(11, u8(checksum >> 16))
compressed.insert(12, u8(checksum >> 8)) compressed.insert(12, u8(checksum >> 8))
compressed.insert(13, u8(checksum)) compressed.insert(13, u8(checksum))
decompressed := decompress(compressed)? decompressed := decompress(compressed)!
assert decompressed == uncompressed.bytes() assert decompressed == uncompressed.bytes()
} }
fn test_gzip_with_invalid_hcrc() ? { fn test_gzip_with_invalid_hcrc() {
uncompressed := 'Hello world!' uncompressed := 'Hello world!'
mut compressed := compress(uncompressed.bytes())? mut compressed := compress(uncompressed.bytes())!
compressed[4] |= 0b0000_0010 compressed[4] |= 0b0000_0010
checksum := crc32.sum(compressed[..10]) checksum := crc32.sum(compressed[..10])
compressed.insert(10, u8(checksum >> 24)) compressed.insert(10, u8(checksum >> 24))
compressed.insert(11, u8(checksum >> 16)) compressed.insert(11, u8(checksum >> 16))
compressed.insert(12, u8(checksum >> 8)) compressed.insert(12, u8(checksum >> 8))
compressed.insert(13, u8(checksum + 1)) compressed.insert(13, u8(checksum + 1))
assert_decompress_error(compressed, 'header checksum verification failed')? assert_decompress_error(compressed, 'header checksum verification failed')!
} }
fn test_gzip_with_invalid_checksum() ? { fn test_gzip_with_invalid_checksum() {
uncompressed := 'Hello world!' uncompressed := 'Hello world!'
mut compressed := compress(uncompressed.bytes())? mut compressed := compress(uncompressed.bytes())!
compressed[compressed.len - 5] += 1 compressed[compressed.len - 5] += 1
assert_decompress_error(compressed, 'checksum verification failed')? assert_decompress_error(compressed, 'checksum verification failed')!
} }
fn test_gzip_with_invalid_length() ? { fn test_gzip_with_invalid_length() {
uncompressed := 'Hello world!' uncompressed := 'Hello world!'
mut compressed := compress(uncompressed.bytes())? mut compressed := compress(uncompressed.bytes())!
compressed[compressed.len - 1] += 1 compressed[compressed.len - 1] += 1
assert_decompress_error(compressed, 'length verification failed, got 12, expected 13')? assert_decompress_error(compressed, 'length verification failed, got 12, expected 13')!
} }
fn test_gzip_with_invalid_flags() ? { fn test_gzip_with_invalid_flags() {
uncompressed := 'Hello world!' uncompressed := 'Hello world!'
mut compressed := compress(uncompressed.bytes())? mut compressed := compress(uncompressed.bytes())!
compressed[4] |= 0b1000_0000 compressed[4] |= 0b1000_0000
assert_decompress_error(compressed, 'reserved flags are set, unsupported field detected')? assert_decompress_error(compressed, 'reserved flags are set, unsupported field detected')!
} }

View file

@ -10,8 +10,8 @@ import compress.zlib
fn main() { fn main() {
uncompressed := 'Hello world!' uncompressed := 'Hello world!'
compressed := zlib.compress(uncompressed.bytes())? compressed := zlib.compress(uncompressed.bytes())!
decompressed := zlib.decompress(compressed)? decompressed := zlib.decompress(compressed)!
assert decompressed == uncompressed.bytes() assert decompressed == uncompressed.bytes()
} }
``` ```

View file

@ -4,14 +4,14 @@ import compress
// compresses an array of bytes using zlib and returns the compressed bytes in a new array // compresses an array of bytes using zlib and returns the compressed bytes in a new array
// Example: compressed := zlib.compress(b)? // Example: compressed := zlib.compress(b)?
pub fn compress(data []u8) ?[]u8 { pub fn compress(data []u8) ![]u8 {
// flags = TDEFL_WRITE_ZLIB_HEADER (0x01000) // flags = TDEFL_WRITE_ZLIB_HEADER (0x01000)
return compress.compress(data, 0x01000) return compress.compress(data, 0x01000)
} }
// decompresses an array of bytes using zlib and returns the decompressed bytes in a new array // decompresses an array of bytes using zlib and returns the decompressed bytes in a new array
// Example: decompressed := zlib.decompress(b)? // Example: decompressed := zlib.decompress(b)?
pub fn decompress(data []u8) ?[]u8 { pub fn decompress(data []u8) ![]u8 {
// flags = TINFL_FLAG_PARSE_ZLIB_HEADER (0x1) // flags = TINFL_FLAG_PARSE_ZLIB_HEADER (0x1)
return compress.decompress(data, 0x1) return compress.decompress(data, 0x1)
} }

View file

@ -1,8 +1,8 @@
module zlib module zlib
fn test_zlib() ? { fn test_zlib() {
uncompressed := 'Hello world!' uncompressed := 'Hello world!'
compressed := compress(uncompressed.bytes())? compressed := compress(uncompressed.bytes())!
decompressed := decompress(compressed)? decompressed := decompress(compressed)!
assert decompressed == uncompressed.bytes() assert decompressed == uncompressed.bytes()
} }

View file

@ -22,7 +22,7 @@ import crypto.rand
fn main() { fn main() {
// remember to save this key somewhere if you ever want to decrypt your data // remember to save this key somewhere if you ever want to decrypt your data
key := rand.bytes(32)? key := rand.bytes(32)!
println('KEY: $key') println('KEY: $key')
// this data is one block (16 bytes) big // this data is one block (16 bytes) big

View file

@ -50,7 +50,7 @@ pub fn (priv PrivateKey) equal(x []u8) bool {
} }
// sign signs the given message with priv. // sign signs the given message with priv.
pub fn (priv PrivateKey) sign(message []u8) ?[]u8 { pub fn (priv PrivateKey) sign(message []u8) ![]u8 {
/* /*
if opts.HashFunc() != crypto.Hash(0) { if opts.HashFunc() != crypto.Hash(0) {
return nil, errors.New("ed25519: cannot sign hashed message") return nil, errors.New("ed25519: cannot sign hashed message")
@ -60,13 +60,13 @@ pub fn (priv PrivateKey) sign(message []u8) ?[]u8 {
} }
// sign`signs the message with privatekey and returns a signature // sign`signs the message with privatekey and returns a signature
pub fn sign(privatekey PrivateKey, message []u8) ?[]u8 { pub fn sign(privatekey PrivateKey, message []u8) ![]u8 {
mut signature := []u8{len: ed25519.signature_size} mut signature := []u8{len: ed25519.signature_size}
sign_generic(mut signature, privatekey, message)? sign_generic(mut signature, privatekey, message)!
return signature return signature
} }
fn sign_generic(mut signature []u8, privatekey []u8, message []u8) ? { fn sign_generic(mut signature []u8, privatekey []u8, message []u8) ! {
if privatekey.len != ed25519.private_key_size { if privatekey.len != ed25519.private_key_size {
panic('ed25519: bad private key length: $privatekey.len') panic('ed25519: bad private key length: $privatekey.len')
} }
@ -74,31 +74,31 @@ fn sign_generic(mut signature []u8, privatekey []u8, message []u8) ? {
mut h := sha512.sum512(seed) mut h := sha512.sum512(seed)
mut s := edwards25519.new_scalar() mut s := edwards25519.new_scalar()
s.set_bytes_with_clamping(h[..32])? s.set_bytes_with_clamping(h[..32])!
mut prefix := h[32..] mut prefix := h[32..]
mut mh := sha512.new() mut mh := sha512.new()
mh.write(prefix)? mh.write(prefix)!
mh.write(message)? mh.write(message)!
mut msg_digest := []u8{cap: sha512.size} mut msg_digest := []u8{cap: sha512.size}
msg_digest = mh.sum(msg_digest) msg_digest = mh.sum(msg_digest)
mut r := edwards25519.new_scalar() mut r := edwards25519.new_scalar()
r.set_uniform_bytes(msg_digest)? r.set_uniform_bytes(msg_digest)!
mut rr := edwards25519.Point{} mut rr := edwards25519.Point{}
rr.scalar_base_mult(mut r) rr.scalar_base_mult(mut r)
mut kh := sha512.new() mut kh := sha512.new()
kh.write(rr.bytes())? kh.write(rr.bytes())!
kh.write(publickey)? kh.write(publickey)!
kh.write(message)? kh.write(message)!
mut hram_digest := []u8{cap: sha512.size} mut hram_digest := []u8{cap: sha512.size}
hram_digest = kh.sum(hram_digest) hram_digest = kh.sum(hram_digest)
mut k := edwards25519.new_scalar() mut k := edwards25519.new_scalar()
k.set_uniform_bytes(hram_digest)? k.set_uniform_bytes(hram_digest)!
mut ss := edwards25519.new_scalar() mut ss := edwards25519.new_scalar()
ss.multiply_add(k, s, r) ss.multiply_add(k, s, r)
@ -108,7 +108,7 @@ fn sign_generic(mut signature []u8, privatekey []u8, message []u8) ? {
} }
// verify reports whether sig is a valid signature of message by publickey. // verify reports whether sig is a valid signature of message by publickey.
pub fn verify(publickey PublicKey, message []u8, sig []u8) ?bool { pub fn verify(publickey PublicKey, message []u8, sig []u8) !bool {
if publickey.len != ed25519.public_key_size { if publickey.len != ed25519.public_key_size {
return error('ed25519: bad public key length: $publickey.len') return error('ed25519: bad public key length: $publickey.len')
} }
@ -118,21 +118,21 @@ pub fn verify(publickey PublicKey, message []u8, sig []u8) ?bool {
} }
mut aa := edwards25519.Point{} mut aa := edwards25519.Point{}
aa.set_bytes(publickey)? aa.set_bytes(publickey)!
mut kh := sha512.new() mut kh := sha512.new()
kh.write(sig[..32])? kh.write(sig[..32])!
kh.write(publickey)? kh.write(publickey)!
kh.write(message)? kh.write(message)!
mut hram_digest := []u8{cap: sha512.size} mut hram_digest := []u8{cap: sha512.size}
hram_digest = kh.sum(hram_digest) hram_digest = kh.sum(hram_digest)
mut k := edwards25519.new_scalar() mut k := edwards25519.new_scalar()
k.set_uniform_bytes(hram_digest)? k.set_uniform_bytes(hram_digest)!
mut ss := edwards25519.new_scalar() mut ss := edwards25519.new_scalar()
ss.set_canonical_bytes(sig[32..])? ss.set_canonical_bytes(sig[32..])!
// [S]B = R + [k]A --> [k](-A) + [S]B = R // [S]B = R + [k]A --> [k](-A) + [S]B = R
mut minus_a := edwards25519.Point{} mut minus_a := edwards25519.Point{}
@ -144,8 +144,8 @@ pub fn verify(publickey PublicKey, message []u8, sig []u8) ?bool {
} }
// generate_key generates a public/private key pair entropy using `crypto.rand`. // generate_key generates a public/private key pair entropy using `crypto.rand`.
pub fn generate_key() ?(PublicKey, PrivateKey) { pub fn generate_key() !(PublicKey, PrivateKey) {
mut seed := rand.bytes(ed25519.seed_size)? mut seed := rand.bytes(ed25519.seed_size)!
privatekey := new_key_from_seed(seed) privatekey := new_key_from_seed(seed)
mut publickey := []u8{len: ed25519.public_key_size} mut publickey := []u8{len: ed25519.public_key_size}

View file

@ -8,11 +8,11 @@ import crypto.ed25519
fn main() { fn main() {
msg := 'Hello Girl' msg := 'Hello Girl'
publ, priv := ed25519.generate_key()? publ, priv := ed25519.generate_key()!
m := msg.bytes() m := msg.bytes()
sig := ed25519.sign(priv, m)? sig := ed25519.sign(priv, m)!
println('=== Message ===') println('=== Message ===')
println('Msg: $msg \nHash: $m') println('Msg: $msg \nHash: $m')
@ -31,7 +31,7 @@ fn main() {
println('signature: R=${sig[0..32].hex()} s=${sig[32..64].hex()}') println('signature: R=${sig[0..32].hex()} s=${sig[32..64].hex()}')
println(' signature (Base64)=${base64.encode(sig)}') println(' signature (Base64)=${base64.encode(sig)}')
rtn := ed25519.verify(publ, m, sig)? rtn := ed25519.verify(publ, m, sig)!
if rtn { if rtn {
println('Signature verified :$rtn') println('Signature verified :$rtn')

View file

@ -27,22 +27,22 @@ fn (z ZeroReader) read(mut buf []u8) ?int {
} }
*/ */
fn test_sign_verify() ? { fn test_sign_verify() {
// mut zero := ZeroReader{} // mut zero := ZeroReader{}
public, private := ed25519.generate_key()? public, private := ed25519.generate_key()!
message := 'test message'.bytes() message := 'test message'.bytes()
sig := ed25519.sign(private, message)? sig := ed25519.sign(private, message)!
res := ed25519.verify(public, message, sig) or { false } res := ed25519.verify(public, message, sig) or { false }
assert res == true assert res == true
wrongmessage := 'wrong message'.bytes() wrongmessage := 'wrong message'.bytes()
res2 := ed25519.verify(public, wrongmessage, sig)? res2 := ed25519.verify(public, wrongmessage, sig)!
assert res2 == false assert res2 == false
} }
fn test_equal() ? { fn test_equal() {
public, private := ed25519.generate_key()? public, private := ed25519.generate_key()!
assert public.equal(public) == true assert public.equal(public) == true
@ -53,13 +53,13 @@ fn test_equal() ? {
}*/ }*/
assert private.equal(private) == true assert private.equal(private) == true
otherpub, otherpriv := ed25519.generate_key()? otherpub, otherpriv := ed25519.generate_key()!
assert public.equal(otherpub) == false assert public.equal(otherpub) == false
assert private.equal(otherpriv) == false assert private.equal(otherpriv) == false
} }
fn test_malleability() ? { fn test_malleability() {
// https://tools.ietf.org/html/rfc8032#section-5.1.7 adds an additional test // https://tools.ietf.org/html/rfc8032#section-5.1.7 adds an additional test
// that s be in [0, order). This prevents someone from adding a multiple of // that s be in [0, order). This prevents someone from adding a multiple of
// order to s and obtaining a second valid signature for the same message. // order to s and obtaining a second valid signature for the same message.
@ -149,7 +149,7 @@ mut:
// This test read a lot of entries in `testdata/sign.input` // This test read a lot of entries in `testdata/sign.input`
// so, maybe need a long time to finish. // so, maybe need a long time to finish.
// be quiet and patient // be quiet and patient
fn test_input_from_djb_ed25519_crypto_sign_input_with_syncpool() ? { fn test_input_from_djb_ed25519_crypto_sign_input_with_syncpool() {
// contents := os.read_lines('testdata/sign.input') or { panic(err) } //[]string // contents := os.read_lines('testdata/sign.input') or { panic(err) } //[]string
mut pool_s := pool.new_pool_processor( mut pool_s := pool.new_pool_processor(
callback: worker_for_string_content callback: worker_for_string_content
@ -174,10 +174,10 @@ fn test_input_from_djb_ed25519_crypto_sign_input_without_syncpool() ? {
lg.fatal('not contains len 5') lg.fatal('not contains len 5')
}*/ }*/
assert parts.len == 5 assert parts.len == 5
privbytes := hex.decode(parts[0])? privbytes := hex.decode(parts[0])!
pubkey := hex.decode(parts[1])? pubkey := hex.decode(parts[1])!
msg := hex.decode(parts[2])? msg := hex.decode(parts[2])!
mut sig := hex.decode(parts[3])? mut sig := hex.decode(parts[3])!
assert pubkey.len == public_key_size assert pubkey.len == public_key_size
sig = sig[..signature_size] sig = sig[..signature_size]
@ -185,10 +185,10 @@ fn test_input_from_djb_ed25519_crypto_sign_input_without_syncpool() ? {
copy(mut priv[..], privbytes) copy(mut priv[..], privbytes)
copy(mut priv[32..], pubkey) copy(mut priv[32..], pubkey)
sig2 := ed25519.sign(priv[..], msg)? sig2 := ed25519.sign(priv[..], msg)!
assert sig == sig2[..] assert sig == sig2[..]
res := ed25519.verify(pubkey, msg, sig2)? res := ed25519.verify(pubkey, msg, sig2)!
assert res == true assert res == true
priv2 := new_key_from_seed(priv[..32]) priv2 := new_key_from_seed(priv[..32])

View file

@ -624,7 +624,7 @@ pub fn (mut v Element) set(a Element) Element {
// Consistent with RFC 7748, the most significant bit (the high bit of the // Consistent with RFC 7748, the most significant bit (the high bit of the
// last byte) is ignored, and non-canonical values (2^255-19 through 2^255-1) // last byte) is ignored, and non-canonical values (2^255-19 through 2^255-1)
// are accepted. Note that this is laxer than specified by RFC 8032. // are accepted. Note that this is laxer than specified by RFC 8032.
pub fn (mut v Element) set_bytes(x []u8) ?Element { pub fn (mut v Element) set_bytes(x []u8) !Element {
if x.len != 32 { if x.len != 32 {
return error('edwards25519: invalid edwards25519 element input size') return error('edwards25519: invalid edwards25519 element input size')
} }

View file

@ -162,7 +162,7 @@ struct SqrtRatioTest {
r string r string
} }
fn test_sqrt_ratio() ? { fn test_sqrt_ratio() {
// From draft-irtf-cfrg-ristretto255-decaf448-00, Appendix A.4. // From draft-irtf-cfrg-ristretto255-decaf448-00, Appendix A.4.
tests := [ tests := [
@ -188,9 +188,9 @@ fn test_sqrt_ratio() ? {
mut elw := Element{} mut elw := Element{}
mut elg := Element{} mut elg := Element{}
u := elu.set_bytes(hex.decode(tt.u)?)? u := elu.set_bytes(hex.decode(tt.u)!)!
v := elv.set_bytes(hex.decode(tt.v)?)? v := elv.set_bytes(hex.decode(tt.v)!)!
want := elw.set_bytes(hex.decode(tt.r)?)? want := elw.set_bytes(hex.decode(tt.r)!)!
mut got, was_square := elg.sqrt_ratio(u, v) mut got, was_square := elg.sqrt_ratio(u, v)
assert got.equal(want) != 0 assert got.equal(want) != 0
@ -201,12 +201,12 @@ fn test_sqrt_ratio() ? {
} }
} }
fn test_set_bytes_normal() ? { fn test_set_bytes_normal() {
for i in 0 .. 15 { for i in 0 .. 15 {
mut el := Element{} mut el := Element{}
mut random_inp := rand.bytes(32)? mut random_inp := rand.bytes(32)!
el = el.set_bytes(random_inp.clone())? el = el.set_bytes(random_inp.clone())!
random_inp[random_inp.len - 1] &= (1 << 7) - 1 random_inp[random_inp.len - 1] &= (1 << 7) - 1
// assert f1(random_inp, el) == true // assert f1(random_inp, el) == true
@ -233,7 +233,7 @@ mut:
b []u8 b []u8
} }
fn test_set_bytes_from_dalek_test_vectors() ? { fn test_set_bytes_from_dalek_test_vectors() {
mut tests := [ mut tests := [
FeRTTest{ FeRTTest{
fe: Element{358744748052810, 1691584618240980, 977650209285361, 1429865912637724, 560044844278676} fe: Element{358744748052810, 1691584618240980, 977650209285361, 1429865912637724, 560044844278676}
@ -249,7 +249,7 @@ fn test_set_bytes_from_dalek_test_vectors() ? {
for _, mut tt in tests { for _, mut tt in tests {
b := tt.fe.bytes() b := tt.fe.bytes()
mut el := Element{} mut el := Element{}
mut fe := el.set_bytes(tt.b)? mut fe := el.set_bytes(tt.b)!
assert b == tt.b assert b == tt.b
assert fe.equal(tt.fe) == 1 assert fe.equal(tt.fe) == 1
@ -267,7 +267,7 @@ fn test_equal() {
assert eq1 == 0 assert eq1 == 0
} }
fn test_invert() ? { fn test_invert() {
mut x := Element{1, 1, 1, 1, 1} mut x := Element{1, 1, 1, 1, 1}
mut one := Element{1, 0, 0, 0, 0} mut one := Element{1, 0, 0, 0, 0}
mut xinv := Element{} mut xinv := Element{}
@ -278,9 +278,9 @@ fn test_invert() ? {
r.reduce() r.reduce()
assert one == r assert one == r
bytes := rand.bytes(32) or { return err } bytes := rand.bytes(32)!
x.set_bytes(bytes)? x.set_bytes(bytes)!
xinv.invert(x) xinv.invert(x)
r.multiply(x, xinv) r.multiply(x, xinv)
@ -363,26 +363,26 @@ fn (mut v Element) to_big_integer() big.Integer {
} }
// from_big_integer sets v = n, and returns v. The bit length of n must not exceed 256. // from_big_integer sets v = n, and returns v. The bit length of n must not exceed 256.
fn (mut v Element) from_big_integer(n big.Integer) ?Element { fn (mut v Element) from_big_integer(n big.Integer) !Element {
if n.binary_str().len > 32 * 8 { if n.binary_str().len > 32 * 8 {
return error('invalid edwards25519 element input size') return error('invalid edwards25519 element input size')
} }
mut bytes, _ := n.bytes() mut bytes, _ := n.bytes()
swap_endianness(mut bytes) // SHOULD I SWAP IT? swap_endianness(mut bytes) // SHOULD I SWAP IT?
v.set_bytes(bytes)? v.set_bytes(bytes)!
return v return v
} }
fn (mut v Element) from_decimal_string(s string) ?Element { fn (mut v Element) from_decimal_string(s string) !Element {
num := big.integer_from_string(s)? num := big.integer_from_string(s)!
v = v.from_big_integer(num)? v = v.from_big_integer(num)!
return v return v
} }
fn test_bytes_big_equivalence() ? { fn test_bytes_big_equivalence() {
mut inp := rand.bytes(32)? mut inp := rand.bytes(32)!
el := Element{} el := Element{}
mut fe := el.generate_element() mut fe := el.generate_element()
mut fe1 := el.generate_element() mut fe1 := el.generate_element()
@ -404,15 +404,15 @@ fn test_bytes_big_equivalence() ? {
// assert big_equivalence(inp, fe, fe1) == true // assert big_equivalence(inp, fe, fe1) == true
} }
fn test_decimal_constants() ? { fn test_decimal_constants() {
sqrtm1string := '19681161376707505956807079304988542015446066515923890162744021073123829784752' sqrtm1string := '19681161376707505956807079304988542015446066515923890162744021073123829784752'
mut el := Element{} mut el := Element{}
mut exp := el.from_decimal_string(sqrtm1string)? mut exp := el.from_decimal_string(sqrtm1string)!
assert sqrt_m1.equal(exp) == 1 assert sqrt_m1.equal(exp) == 1
dstring := '37095705934669439343138083508754565189542113879843219016388785533085940283555' dstring := '37095705934669439343138083508754565189542113879843219016388785533085940283555'
exp = el.from_decimal_string(dstring)? exp = el.from_decimal_string(dstring)!
mut d := d_const mut d := d_const
assert d.equal(exp) == 1 assert d.equal(exp) == 1

View file

@ -44,12 +44,12 @@ fn test_bytes_montgomery() {
} }
}*/ }*/
fn test_bytes_montgomery_sodium() ? { fn test_bytes_montgomery_sodium() {
// Generated with libsodium.js 1.0.18 // Generated with libsodium.js 1.0.18
// crypto_sign_keypair().pubkey // crypto_sign_keypair().pubkey
pubkey := '3bf918ffc2c955dc895bf145f566fb96623c1cadbe040091175764b5fde322c0' pubkey := '3bf918ffc2c955dc895bf145f566fb96623c1cadbe040091175764b5fde322c0'
mut p := Point{} mut p := Point{}
p.set_bytes(hex.decode(pubkey)?)? p.set_bytes(hex.decode(pubkey)!)!
// crypto_sign_ed25519_pk_to_curve25519(pubkey) // crypto_sign_ed25519_pk_to_curve25519(pubkey)
want := 'efc6c9d0738e9ea18d738ad4a2653631558931b0f1fde4dd58c436d19686dc28' want := 'efc6c9d0738e9ea18d738ad4a2653631558931b0f1fde4dd58c436d19686dc28'
@ -113,9 +113,9 @@ fn fn_cofactor(mut data []u8) bool {
return p8.equal(pp) == 1 return p8.equal(pp) == 1
} }
fn test_mult_by_cofactor() ? { fn test_mult_by_cofactor() {
mut loworder := Point{} mut loworder := Point{}
mut data := rand.bytes(64)? mut data := rand.bytes(64)!
assert fn_cofactor(mut data) == true assert fn_cofactor(mut data) == true
} }

View file

@ -18,30 +18,30 @@ const (
gen_point = generator() or { panic(err) } gen_point = generator() or { panic(err) }
) )
fn d_const_generate() ?Element { fn d_const_generate() !Element {
mut v := Element{} mut v := Element{}
v.set_bytes(edwards25519.d_bytes)? v.set_bytes(edwards25519.d_bytes)!
return v return v
} }
fn d2_const_generate() ?Element { fn d2_const_generate() !Element {
mut v := Element{} mut v := Element{}
v.add(edwards25519.d_const, edwards25519.d_const) v.add(edwards25519.d_const, edwards25519.d_const)
return v return v
} }
// id_point_generate is the point at infinity. // id_point_generate is the point at infinity.
fn id_point_generate() ?Point { fn id_point_generate() !Point {
mut p := Point{} mut p := Point{}
p.set_bytes(edwards25519.id_bytes)? p.set_bytes(edwards25519.id_bytes)!
return p return p
} }
// generator is the canonical curve basepoint. See TestGenerator for the // generator is the canonical curve basepoint. See TestGenerator for the
// correspondence of this encoding with the values in RFC 8032. // correspondence of this encoding with the values in RFC 8032.
fn generator() ?Point { fn generator() !Point {
mut p := Point{} mut p := Point{}
p.set_bytes(edwards25519.gen_bytes)? p.set_bytes(edwards25519.gen_bytes)!
return p return p
} }
@ -117,7 +117,7 @@ fn (mut v ProjectiveP2) zero() ProjectiveP2 {
// Note that set_bytes accepts all non-canonical encodings of valid points. // Note that set_bytes accepts all non-canonical encodings of valid points.
// That is, it follows decoding rules that match most implementations in // That is, it follows decoding rules that match most implementations in
// the ecosystem rather than RFC 8032. // the ecosystem rather than RFC 8032.
pub fn (mut v Point) set_bytes(x []u8) ?Point { pub fn (mut v Point) set_bytes(x []u8) !Point {
// Specifically, the non-canonical encodings that are accepted are // Specifically, the non-canonical encodings that are accepted are
// 1) the ones where the edwards25519 element is not reduced (see the // 1) the ones where the edwards25519 element is not reduced (see the
// (*edwards25519.Element).set_bytes docs) and // (*edwards25519.Element).set_bytes docs) and

View file

@ -4,7 +4,7 @@ import encoding.hex
const zero_point = Point{fe_zero, fe_zero, fe_zero, fe_zero} const zero_point = Point{fe_zero, fe_zero, fe_zero, fe_zero}
fn test_invalid_encodings() ? { fn test_invalid_encodings() {
// An invalid point, that also happens to have y > p. // An invalid point, that also happens to have y > p.
invalid := 'efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f' invalid := 'efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f'
inv_bytes := hex.decode(invalid) or { panic(err) } inv_bytes := hex.decode(invalid) or { panic(err) }
@ -17,7 +17,7 @@ fn test_invalid_encodings() ? {
assert check_on_curve(p) == true assert check_on_curve(p) == true
} }
fn test_add_sub_neg_on_basepoint() ? { fn test_add_sub_neg_on_basepoint() {
bgp := new_generator_point() bgp := new_generator_point()
mut idp := new_identity_point() mut idp := new_identity_point()
mut checklhs := Point{} mut checklhs := Point{}
@ -52,7 +52,7 @@ struct NonCanonicalTest {
canonical string canonical string
} }
fn test_non_canonical_points() ? { fn test_non_canonical_points() {
tests := [ tests := [
// Points with x = 0 and the sign bit set. With x = 0 the curve equation // Points with x = 0 and the sign bit set. With x = 0 the curve equation
// gives y² = 1, so y = ±1. 1 has two valid encodings. // gives y² = 1, so y = ±1. 1 has two valid encodings.
@ -96,11 +96,11 @@ fn test_non_canonical_points() ? {
// t.Run(tt.name, func(t *testing.T) { // t.Run(tt.name, func(t *testing.T) {
// p1, err := new(Point).SetBytes(decodeHex(tt.encoding)) // p1, err := new(Point).SetBytes(decodeHex(tt.encoding))
mut p1 := Point{} mut p1 := Point{}
p1.set_bytes(hex.decode(tt.encoding)?)? p1.set_bytes(hex.decode(tt.encoding)!)!
// p2, err := new(Point).SetBytes(decodeHex(tt.canonical)) // p2, err := new(Point).SetBytes(decodeHex(tt.canonical))
mut p2 := Point{} mut p2 := Point{}
p2.set_bytes(hex.decode(tt.canonical)?)? p2.set_bytes(hex.decode(tt.canonical)!)!
assert p1.equal(p2) == 1 assert p1.equal(p2) == 1
assert p1.bytes() == p2.bytes() assert p1.bytes() == p2.bytes()

View file

@ -86,7 +86,7 @@ pub fn (mut s Scalar) set(x Scalar) Scalar {
// set_uniform_bytes sets s to an uniformly distributed value given 64 uniformly // set_uniform_bytes sets s to an uniformly distributed value given 64 uniformly
// distributed random bytes. If x is not of the right length, set_uniform_bytes // distributed random bytes. If x is not of the right length, set_uniform_bytes
// returns an error, and the receiver is unchanged. // returns an error, and the receiver is unchanged.
pub fn (mut s Scalar) set_uniform_bytes(x []u8) ?Scalar { pub fn (mut s Scalar) set_uniform_bytes(x []u8) !Scalar {
if x.len != 64 { if x.len != 64 {
return error('edwards25519: invalid set_uniform_bytes input length') return error('edwards25519: invalid set_uniform_bytes input length')
} }
@ -102,7 +102,7 @@ pub fn (mut s Scalar) set_uniform_bytes(x []u8) ?Scalar {
// set_canonical_bytes sets s = x, where x is a 32-byte little-endian encoding of // set_canonical_bytes sets s = x, where x is a 32-byte little-endian encoding of
// s, and returns s. If x is not a canonical encoding of s, set_canonical_bytes // s, and returns s. If x is not a canonical encoding of s, set_canonical_bytes
// returns an error, and the receiver is unchanged. // returns an error, and the receiver is unchanged.
pub fn (mut s Scalar) set_canonical_bytes(x []u8) ?Scalar { pub fn (mut s Scalar) set_canonical_bytes(x []u8) !Scalar {
if x.len != 32 { if x.len != 32 {
return error('invalid scalar length') return error('invalid scalar length')
} }
@ -152,7 +152,7 @@ fn is_reduced(s Scalar) bool {
// expected as long as it is applied to points on the prime order subgroup, like // expected as long as it is applied to points on the prime order subgroup, like
// in Ed25519. In fact, it is lost to history why RFC 8032 adopted the // in Ed25519. In fact, it is lost to history why RFC 8032 adopted the
// irrelevant RFC 7748 clamping, but it is now required for compatibility. // irrelevant RFC 7748 clamping, but it is now required for compatibility.
pub fn (mut s Scalar) set_bytes_with_clamping(x []u8) ?Scalar { pub fn (mut s Scalar) set_bytes_with_clamping(x []u8) !Scalar {
// The description above omits the purpose of the high bits of the clamping // The description above omits the purpose of the high bits of the clamping
// for brevity, but those are also lost to reductions, and are also // for brevity, but those are also lost to reductions, and are also
// irrelevant to edwards25519 as they protect against a specific // irrelevant to edwards25519 as they protect against a specific
@ -1070,7 +1070,7 @@ fn (mut s Scalar) signed_radix16() []i8 {
// utility function // utility function
// generate returns a valid (reduced modulo l) Scalar with a distribution // generate returns a valid (reduced modulo l) Scalar with a distribution
// weighted towards high, low, and edge values. // weighted towards high, low, and edge values.
fn generate_scalar(size int) ?Scalar { fn generate_scalar(size int) !Scalar {
/* /*
s := scZero s := scZero
diceRoll := rand.Intn(100) diceRoll := rand.Intn(100)
@ -1115,7 +1115,7 @@ fn generate_scalar(size int) ?Scalar {
// rand.Read(s.s[:16]) // read random bytes and fill buf // rand.Read(s.s[:16]) // read random bytes and fill buf
// using builtin rand.read([]buf) // using builtin rand.read([]buf)
rand.read(mut s.s[..16]) rand.read(mut s.s[..16])
// buf := rand.read(s.s[..16].len)? // buf := rand.read(s.s[..16].len)!
// copy(mut s.s[..16], buf) // copy(mut s.s[..16], buf)
/* /*
@ -1132,7 +1132,7 @@ fn generate_scalar(size int) ?Scalar {
// Read generates len(p) random bytes and writes them into p // Read generates len(p) random bytes and writes them into p
// rand.Read(s.s[:16]) // rand.Read(s.s[:16])
rand.read(mut s.s[..16]) rand.read(mut s.s[..16])
// buf := rand.read(s.s[..16].len)? // buf := rand.read(s.s[..16].len)!
// copy(mut s.s[..16], buf) // copy(mut s.s[..16], buf)
/* /*
@ -1148,7 +1148,7 @@ fn generate_scalar(size int) ?Scalar {
// of being out of the latter range). // of being out of the latter range).
// rand.Read(s.s[:]) // rand.Read(s.s[:])
rand.read(mut s.s[..]) rand.read(mut s.s[..])
// buf := crand.read(s.s.len)? // buf := crand.read(s.s.len)!
// copy(mut s.s[..], buf) // copy(mut s.s[..], buf)
/* /*
@ -1164,10 +1164,10 @@ fn generate_scalar(size int) ?Scalar {
type NotZeroScalar = Scalar type NotZeroScalar = Scalar
fn generate_notzero_scalar(size int) ?NotZeroScalar { fn generate_notzero_scalar(size int) !NotZeroScalar {
mut s := Scalar{} mut s := Scalar{}
for s == edwards25519.sc_zero { for s == edwards25519.sc_zero {
s = generate_scalar(size)? s = generate_scalar(size)!
} }
return NotZeroScalar(s) return NotZeroScalar(s)
} }

View file

@ -24,9 +24,9 @@ fn negate_aliasing(mut v Scalar, x Scalar) Scalar {
return v.negate(x) return v.negate(x)
} }
fn test_check_aliasing_oneargs() ? { fn test_check_aliasing_oneargs() {
x := generate_notzero_scalar(10)? x := generate_notzero_scalar(10)!
mut v := generate_notzero_scalar(10)? mut v := generate_notzero_scalar(10)!
out := check_aliasing_onearg(negate_aliasing, mut v, x) out := check_aliasing_onearg(negate_aliasing, mut v, x)
assert out == true assert out == true
} }
@ -43,12 +43,12 @@ fn subtract_aliasing(mut v Scalar, x Scalar, y Scalar) Scalar {
return v.subtract(x, y) return v.subtract(x, y)
} }
fn test_check_aliasing_twoargs() ? { fn test_check_aliasing_twoargs() {
fn_with_twoargs := [add_aliasing, multiply_aliasing, subtract_aliasing] fn_with_twoargs := [add_aliasing, multiply_aliasing, subtract_aliasing]
for f in fn_with_twoargs { for f in fn_with_twoargs {
mut v := generate_notzero_scalar(10)? mut v := generate_notzero_scalar(10)!
x := generate_notzero_scalar(10)? x := generate_notzero_scalar(10)!
y := generate_notzero_scalar(10)? y := generate_notzero_scalar(10)!
out := check_aliasing_twoargs(f, mut v, x, y) out := check_aliasing_twoargs(f, mut v, x, y)
assert out == true assert out == true
} }

View file

@ -68,7 +68,7 @@ fn fg(sc Scalar) bool {
return is_reduced(sc) return is_reduced(sc)
} }
fn test_scalar_generate() ? { fn test_scalar_generate() {
for i in 0 .. 15 { for i in 0 .. 15 {
sc := generate_scalar(1000) or { panic(err) } sc := generate_scalar(1000) or { panic(err) }
@ -77,7 +77,7 @@ fn test_scalar_generate() ? {
} }
// //
fn test_scalar_set_canonical_bytes() ? { fn test_scalar_set_canonical_bytes() {
for i in 0 .. 10 { for i in 0 .. 10 {
mut buf := rand.bytes(32) or { panic(err) } mut buf := rand.bytes(32) or { panic(err) }
mut sc := generate_scalar(1000) or { panic(err) } mut sc := generate_scalar(1000) or { panic(err) }
@ -89,10 +89,10 @@ fn test_scalar_set_canonical_bytes() ? {
} }
} }
fn test_scalar_set_canonical_bytes_round_trip() ? { fn test_scalar_set_canonical_bytes_round_trip() {
for i in 0 .. 10 { for i in 0 .. 10 {
mut sc1 := generate_scalar(2)? mut sc1 := generate_scalar(2)!
mut sc2 := generate_scalar(6)? mut sc2 := generate_scalar(6)!
sc2.set_canonical_bytes(sc1.bytes()) or { panic(err) } sc2.set_canonical_bytes(sc1.bytes()) or { panic(err) }
assert sc1 == sc2 assert sc1 == sc2
@ -105,7 +105,7 @@ const (
} }
) )
fn test_scalar_set_canonical_bytes_on_noncanonical_value() ? { fn test_scalar_set_canonical_bytes_on_noncanonical_value() {
mut b := sc_minus_one.s mut b := sc_minus_one.s
b[31] += 1 b[31] += 1
@ -115,16 +115,16 @@ fn test_scalar_set_canonical_bytes_on_noncanonical_value() ? {
assert s == sc_one assert s == sc_one
} }
fn test_scalar_set_uniform_bytes() ? { fn test_scalar_set_uniform_bytes() {
// mod, _ := new(big.Integer).SetString("27742317777372353535851937790883648493", 10) // mod, _ := new(big.Integer).SetString("27742317777372353535851937790883648493", 10)
mut mod := big.integer_from_string('27742317777372353535851937790883648493')? mut mod := big.integer_from_string('27742317777372353535851937790883648493')!
// mod.Add(mod, new(big.Integer).Lsh(big.NewInt(1), 252)) // mod.Add(mod, new(big.Integer).Lsh(big.NewInt(1), 252))
mod = mod + big.integer_from_i64(1).lshift(252) mod = mod + big.integer_from_i64(1).lshift(252)
mut sc := generate_scalar(100)? mut sc := generate_scalar(100)!
inp := rand.bytes(64)? inp := rand.bytes(64)!
sc.set_uniform_bytes(inp[..])? sc.set_uniform_bytes(inp[..])!
assert is_reduced(sc) == true assert is_reduced(sc) == true
scbig := bigint_from_le_bytes(sc.s[..]) scbig := bigint_from_le_bytes(sc.s[..])
@ -189,10 +189,10 @@ fn test_scalar_set_bytes_with_clamping() {
assert want2 == got2 assert want2 == got2
} }
fn test_scalar_multiply_distributes_over_add() ? { fn test_scalar_multiply_distributes_over_add() {
x := generate_scalar(100)? x := generate_scalar(100)!
y := generate_scalar(100)? y := generate_scalar(100)!
z := generate_scalar(100)? z := generate_scalar(100)!
// Compute t1 = (x+y)*z // Compute t1 = (x+y)*z
mut t1 := Scalar{} mut t1 := Scalar{}

View file

@ -91,11 +91,11 @@ fn test_scalar_mult_distributes_over_add() {
assert check.equal(r) == 1 assert check.equal(r) == 1
} }
fn test_scalarmult_non_identity_point() ? { fn test_scalarmult_non_identity_point() {
// Check whether p.ScalarMult and q.ScalaBaseMult give the same, // Check whether p.ScalarMult and q.ScalaBaseMult give the same,
// when p and q are originally set to the base point. // when p and q are originally set to the base point.
mut x := generate_scalar(5000)? mut x := generate_scalar(5000)!
mut p := Point{} mut p := Point{}
mut q := Point{} mut q := Point{}

View file

@ -1,7 +1,7 @@
import crypto.rand import crypto.rand
fn test_reading() ? { fn test_reading() {
a := rand.read(32)? a := rand.read(32)!
// dump(a.hex()) // dump(a.hex())
assert a.len == 32 assert a.len == 32
mut histogram := [256]int{} mut histogram := [256]int{}

View file

@ -18,6 +18,6 @@ pub fn (err ReadError) msg() string {
// See also rand.bytes(), if you do not need really random bytes, // See also rand.bytes(), if you do not need really random bytes,
// but instead pseudo random ones, from a pseudo random generator // but instead pseudo random ones, from a pseudo random generator
// that can be seeded, and that is usually faster. // that can be seeded, and that is usually faster.
pub fn bytes(bytes_needed int) ?[]u8 { pub fn bytes(bytes_needed int) ![]u8 {
return read(bytes_needed) return read(bytes_needed)
} }

View file

@ -11,7 +11,7 @@ module rand
fn C.SecRandomCopyBytes(rnd C.SecRandomRef, count usize, bytes voidptr) int fn C.SecRandomCopyBytes(rnd C.SecRandomRef, count usize, bytes voidptr) int
// read returns an array of `bytes_needed` random bytes read from the OS. // read returns an array of `bytes_needed` random bytes read from the OS.
pub fn read(bytes_needed int) ?[]u8 { pub fn read(bytes_needed int) ![]u8 {
mut buffer := []u8{len: bytes_needed} mut buffer := []u8{len: bytes_needed}
status := C.SecRandomCopyBytes(C.SecRandomRef(0), bytes_needed, buffer.data) status := C.SecRandomCopyBytes(C.SecRandomRef(0), bytes_needed, buffer.data)
if status != 0 { if status != 0 {

View file

@ -4,6 +4,6 @@
module rand module rand
// read returns an array of `bytes_needed` random bytes read from the OS. // read returns an array of `bytes_needed` random bytes read from the OS.
pub fn read(bytes_needed int) ?[]u8 { pub fn read(bytes_needed int) ![]u8 {
return error('rand.read is not implemented on this platform') return error('rand.read is not implemented on this platform')
} }

View file

@ -9,7 +9,7 @@ module rand
fn C.arc4random_buf(p &byte, n usize) fn C.arc4random_buf(p &byte, n usize)
// read returns an array of `bytes_needed` random bytes read from the OS. // read returns an array of `bytes_needed` random bytes read from the OS.
pub fn read(bytes_needed int) ?[]u8 { pub fn read(bytes_needed int) ![]u8 {
mut buffer := unsafe { malloc_noscan(bytes_needed) } mut buffer := unsafe { malloc_noscan(bytes_needed) }
C.arc4random_buf(buffer, bytes_needed) C.arc4random_buf(buffer, bytes_needed)
return unsafe { buffer.vbytes(bytes_needed) } return unsafe { buffer.vbytes(bytes_needed) }

View file

@ -10,7 +10,7 @@ const (
) )
// read returns an array of `bytes_needed` random bytes read from the OS. // read returns an array of `bytes_needed` random bytes read from the OS.
pub fn read(bytes_needed int) ?[]u8 { pub fn read(bytes_needed int) ![]u8 {
mut buffer := unsafe { vcalloc_noscan(bytes_needed) } mut buffer := unsafe { vcalloc_noscan(bytes_needed) }
mut bytes_read := 0 mut bytes_read := 0
mut remaining_bytes := bytes_needed mut remaining_bytes := bytes_needed

View file

@ -9,7 +9,7 @@ module rand
fn C.arc4random_buf(p &byte, n usize) fn C.arc4random_buf(p &byte, n usize)
// read returns an array of `bytes_needed` random bytes read from the OS. // read returns an array of `bytes_needed` random bytes read from the OS.
pub fn read(bytes_needed int) ?[]u8 { pub fn read(bytes_needed int) ![]u8 {
mut buffer := unsafe { malloc_noscan(bytes_needed) } mut buffer := unsafe { malloc_noscan(bytes_needed) }
C.arc4random_buf(buffer, bytes_needed) C.arc4random_buf(buffer, bytes_needed)
return unsafe { buffer.vbytes(bytes_needed) } return unsafe { buffer.vbytes(bytes_needed) }

View file

@ -13,7 +13,7 @@ const (
) )
// read returns an array of `bytes_needed` random bytes read from the OS. // read returns an array of `bytes_needed` random bytes read from the OS.
pub fn read(bytes_needed int) ?[]u8 { pub fn read(bytes_needed int) ![]u8 {
mut buffer := unsafe { malloc_noscan(bytes_needed) } mut buffer := unsafe { malloc_noscan(bytes_needed) }
mut bytes_read := 0 mut bytes_read := 0
mut remaining_bytes := bytes_needed mut remaining_bytes := bytes_needed

View file

@ -14,7 +14,7 @@ const (
) )
// read returns an array of `bytes_needed` random bytes read from the OS. // read returns an array of `bytes_needed` random bytes read from the OS.
pub fn read(bytes_needed int) ?[]u8 { pub fn read(bytes_needed int) ![]u8 {
mut buffer := []u8{len: bytes_needed} mut buffer := []u8{len: bytes_needed}
// use bcrypt_use_system_preferred_rng because we passed null as algo // use bcrypt_use_system_preferred_rng because we passed null as algo
status := C.BCryptGenRandom(0, buffer.data, bytes_needed, rand.bcrypt_use_system_preferred_rng) status := C.BCryptGenRandom(0, buffer.data, bytes_needed, rand.bcrypt_use_system_preferred_rng)

View file

@ -8,7 +8,7 @@ import math.bits
import encoding.binary import encoding.binary
// int_u64 returns a random unsigned 64-bit integer `u64` read from a real OS source of entropy. // int_u64 returns a random unsigned 64-bit integer `u64` read from a real OS source of entropy.
pub fn int_u64(max u64) ?u64 { pub fn int_u64(max u64) !u64 {
bitlen := bits.len_64(max) bitlen := bits.len_64(max)
if bitlen == 0 { if bitlen == 0 {
return u64(0) return u64(0)
@ -20,7 +20,7 @@ pub fn int_u64(max u64) ?u64 {
} }
mut n := u64(0) mut n := u64(0)
for { for {
mut bytes := read(k)? mut bytes := read(k)!
bytes[0] &= u8(int(u64(1) << b) - 1) bytes[0] &= u8(int(u64(1) << b) - 1)
x := bytes_to_u64(bytes) x := bytes_to_u64(bytes)
n = x[0] n = x[0]

View file

@ -22,7 +22,7 @@ mut:
// new_cipher creates and returns a new Cipher. The key argument should be the // new_cipher creates and returns a new Cipher. The key argument should be the
// RC4 key, at least 1 byte and at most 256 bytes. // RC4 key, at least 1 byte and at most 256 bytes.
pub fn new_cipher(key []u8) ?Cipher { pub fn new_cipher(key []u8) !Cipher {
if key.len < 1 || key.len > 256 { if key.len < 1 || key.len > 256 {
return error('crypto.rc4: invalid key size ' + key.len.str()) return error('crypto.rc4: invalid key size ' + key.len.str())
} }

View file

@ -56,7 +56,7 @@ pub fn new() &Digest {
// write writes the contents of `p_` to the internal hash representation. // write writes the contents of `p_` to the internal hash representation.
[manualfree] [manualfree]
pub fn (mut d Digest) write(p_ []u8) ?int { pub fn (mut d Digest) write(p_ []u8) !int {
nn := p_.len nn := p_.len
unsafe { unsafe {
mut p := p_ mut p := p_

View file

@ -90,7 +90,7 @@ pub fn new224() &Digest {
} }
// write writes the contents of `p_` to the internal hash representation. // write writes the contents of `p_` to the internal hash representation.
pub fn (mut d Digest) write(p_ []u8) ?int { pub fn (mut d Digest) write(p_ []u8) !int {
unsafe { unsafe {
mut p := p_ mut p := p_
nn := p.len nn := p.len

View file

@ -149,7 +149,7 @@ fn new384() &Digest {
} }
// write writes the contents of `p_` to the internal hash representation. // write writes the contents of `p_` to the internal hash representation.
pub fn (mut d Digest) write(p_ []u8) ?int { pub fn (mut d Digest) write(p_ []u8) !int {
unsafe { unsafe {
mut p := p_ mut p := p_
nn := p.len nn := p.len

View file

@ -42,7 +42,7 @@ pub fn (alphabet Alphabet) str() string {
// new_alphabet instantiates an Alphabet object based on // new_alphabet instantiates an Alphabet object based on
// the provided characters // the provided characters
pub fn new_alphabet(str string) ?Alphabet { pub fn new_alphabet(str string) !Alphabet {
if str.len != 58 { if str.len != 58 {
return error(@MOD + '.' + @FN + ': string must be 58 characters in length') return error(@MOD + '.' + @FN + ': string must be 58 characters in length')
} }

View file

@ -5,12 +5,12 @@ module base58
import math import math
// encode_int encodes any integer type to base58 string with Bitcoin alphabet // encode_int encodes any integer type to base58 string with Bitcoin alphabet
pub fn encode_int(input int) ?string { pub fn encode_int(input int) !string {
return encode_int_walpha(input, btc_alphabet) return encode_int_walpha(input, btc_alphabet)
} }
// encode_int_walpha any integer type to base58 string with custom alphabet // encode_int_walpha any integer type to base58 string with custom alphabet
pub fn encode_int_walpha(input int, alphabet Alphabet) ?string { pub fn encode_int_walpha(input int, alphabet Alphabet) !string {
if input <= 0 { if input <= 0 {
return error(@MOD + '.' + @FN + ': input must be greater than zero') return error(@MOD + '.' + @FN + ': input must be greater than zero')
} }
@ -97,12 +97,12 @@ pub fn encode_walpha_bytes(input []u8, alphabet Alphabet) []u8 {
} }
// decode_int decodes base58 string to an integer with Bitcoin alphabet // decode_int decodes base58 string to an integer with Bitcoin alphabet
pub fn decode_int(input string) ?int { pub fn decode_int(input string) !int {
return decode_int_walpha(input, btc_alphabet) return decode_int_walpha(input, btc_alphabet)
} }
// decode_int_walpha decodes base58 string to an integer with custom alphabet // decode_int_walpha decodes base58 string to an integer with custom alphabet
pub fn decode_int_walpha(input string, alphabet Alphabet) ?int { pub fn decode_int_walpha(input string, alphabet Alphabet) !int {
mut total := 0 // to hold the results mut total := 0 // to hold the results
b58 := input.reverse() b58 := input.reverse()
for i, ch in b58 { for i, ch in b58 {
@ -121,27 +121,27 @@ pub fn decode_int_walpha(input string, alphabet Alphabet) ?int {
} }
// decode decodes the base58 input string, using the Bitcoin alphabet // decode decodes the base58 input string, using the Bitcoin alphabet
pub fn decode(str string) ?string { pub fn decode(str string) !string {
return decode_walpha(str, btc_alphabet) return decode_walpha(str, btc_alphabet)
} }
// decode_bytes decodes the base58 encoded input array, using the Bitcoin alphabet // decode_bytes decodes the base58 encoded input array, using the Bitcoin alphabet
pub fn decode_bytes(input []u8) ?[]u8 { pub fn decode_bytes(input []u8) ![]u8 {
return decode_walpha_bytes(input, btc_alphabet) return decode_walpha_bytes(input, btc_alphabet)
} }
// decode_walpha decodes the base58 encoded input string, using custom alphabet // decode_walpha decodes the base58 encoded input string, using custom alphabet
pub fn decode_walpha(input string, alphabet Alphabet) ?string { pub fn decode_walpha(input string, alphabet Alphabet) !string {
if input.len == 0 { if input.len == 0 {
return '' return ''
} }
bin := input.bytes() bin := input.bytes()
res := decode_walpha_bytes(bin, alphabet)? res := decode_walpha_bytes(bin, alphabet)!
return res.bytestr() return res.bytestr()
} }
// decode_walpha_bytes decodes the base58 encoded input array using a custom alphabet // decode_walpha_bytes decodes the base58 encoded input array using a custom alphabet
pub fn decode_walpha_bytes(input []u8, alphabet Alphabet) ?[]u8 { pub fn decode_walpha_bytes(input []u8, alphabet Alphabet) ![]u8 {
if input.len == 0 { if input.len == 0 {
return [] return []
} }

View file

@ -1,41 +1,34 @@
module base58 module base58
fn main() { fn test_encode_int() {
test_encode_int() or {}
test_decode_int() or {}
test_encode_string()
test_fails() or {}
}
fn test_encode_int() ? {
a := 0x24 // should be 'd' in base58 a := 0x24 // should be 'd' in base58
assert encode_int(a)? == 'd' assert encode_int(a)! == 'd'
test_encode_int_walpha()? test_encode_int_walpha()
} }
fn test_encode_int_walpha() ? { fn test_encode_int_walpha() {
// random alphabet // random alphabet
abc := new_alphabet('abcdefghij\$lmnopqrstuvwxyz0123456789_ABCDEFGHIJLMNOPQRSTUV') or { abc := new_alphabet('abcdefghij\$lmnopqrstuvwxyz0123456789_ABCDEFGHIJLMNOPQRSTUV') or {
panic(@MOD + '.' + @FN + ': this should never happen') panic(@MOD + '.' + @FN + ': this should never happen')
} }
a := 0x24 // should be '_' in base58 with our custom alphabet a := 0x24 // should be '_' in base58 with our custom alphabet
assert encode_int_walpha(a, abc)? == '_' assert encode_int_walpha(a, abc)! == '_'
} }
fn test_decode_int() ? { fn test_decode_int() {
a := 'd' a := 'd'
assert decode_int(a)? == 0x24 assert decode_int(a)! == 0x24
test_decode_int_walpha()? test_decode_int_walpha()
} }
fn test_decode_int_walpha() ? { fn test_decode_int_walpha() {
abc := new_alphabet('abcdefghij\$lmnopqrstuvwxyz0123456789_ABCDEFGHIJLMNOPQRSTUV') or { abc := new_alphabet('abcdefghij\$lmnopqrstuvwxyz0123456789_ABCDEFGHIJLMNOPQRSTUV') or {
panic(@MOD + '.' + @FN + ': this should never happen') panic(@MOD + '.' + @FN + ': this should never happen')
} }
a := '_' a := '_'
assert decode_int_walpha(a, abc)? == 0x24 assert decode_int_walpha(a, abc)! == 0x24
} }
fn test_encode_string() { fn test_encode_string() {
@ -49,18 +42,18 @@ fn test_encode_string() {
assert encode_walpha(a, abc) == '0P7yfPSL0pQh2L5' assert encode_walpha(a, abc) == '0P7yfPSL0pQh2L5'
} }
fn test_decode_string() ? { fn test_decode_string() {
a := 'TtaR6twpTGu8VpY' a := 'TtaR6twpTGu8VpY'
assert decode(a)? == 'lorem ipsum' assert decode(a)! == 'lorem ipsum'
abc := new_alphabet('abcdefghij\$lmnopqrstuvwxyz0123456789_ABCDEFGHIJLMNOPQRSTUV') or { abc := new_alphabet('abcdefghij\$lmnopqrstuvwxyz0123456789_ABCDEFGHIJLMNOPQRSTUV') or {
panic(@MOD + '.' + @FN + ': this should never happen') panic(@MOD + '.' + @FN + ': this should never happen')
} }
b := '0P7yfPSL0pQh2L5' b := '0P7yfPSL0pQh2L5'
assert decode_walpha(b, abc)? == 'lorem ipsum' assert decode_walpha(b, abc)! == 'lorem ipsum'
} }
fn test_fails() ? { fn test_fails() ! {
a := -238 a := -238
b := 0 b := 0
if z := encode_int(a) { if z := encode_int(a) {

View file

@ -1,7 +1,7 @@
import encoding.base58 import encoding.base58
import encoding.hex import encoding.hex
fn test_encode() ? { fn test_encode() {
for input, expected in { for input, expected in {
'': '' '': ''
'6263': '2PMCRQ' '6263': '2PMCRQ'
@ -14,20 +14,20 @@ fn test_encode() ? {
} }
} }
fn test_encode_int() ? { fn test_encode_int() {
for input, expected in { for input, expected in {
0x6263: '8VG' 0x6263: '8VG'
0x61: '2g' 0x61: '2g'
0x626262: 'a3gV' 0x626262: 'a3gV'
0x636363: 'aPEr' 0x636363: 'aPEr'
} { } {
output := base58.encode_int(input)? output := base58.encode_int(input)!
println('> input: 0x${input:x} | => output: `$output`') println('> input: 0x${input:x} | => output: `$output`')
assert output == expected assert output == expected
} }
} }
fn test_decode() ? { fn test_decode() {
for output, expected in { for output, expected in {
'USm3fpXnKG5EUBx2ndxBDMPVciP5hGey2Jh4NDv6gmeo1LkMeiKrLJUUBk6Z': 'The quick brown fox jumps over the lazy dog.' 'USm3fpXnKG5EUBx2ndxBDMPVciP5hGey2Jh4NDv6gmeo1LkMeiKrLJUUBk6Z': 'The quick brown fox jumps over the lazy dog.'
'11StV1DL6CwTryKyV': '\x00\x00hello world' '11StV1DL6CwTryKyV': '\x00\x00hello world'
@ -35,7 +35,7 @@ fn test_decode() ? {
'14cxpo3MBCYYWCgF74SWTdcmxipnGUsPw3': hex.decode('0027b5891b01da2db74cde1689a97a2acbe23d5fb1c0205bf6')?.bytestr() '14cxpo3MBCYYWCgF74SWTdcmxipnGUsPw3': hex.decode('0027b5891b01da2db74cde1689a97a2acbe23d5fb1c0205bf6')?.bytestr()
'3vQB7B6MrGQZaxCuFg4oh': hex.decode('68656c6c6f20776f726c64bc62d4b8')?.bytestr() '3vQB7B6MrGQZaxCuFg4oh': hex.decode('68656c6c6f20776f726c64bc62d4b8')?.bytestr()
} { } {
input := base58.decode(output)? input := base58.decode(output)!
println('> output: `$output` | decoded input: `$input` | bytes: $input.bytes().hex()') println('> output: `$output` | decoded input: `$input` | bytes: $input.bytes().hex()')
assert input.bytes().hex() == expected.bytes().hex() assert input.bytes().hex() == expected.bytes().hex()
} }

View file

@ -68,8 +68,8 @@ pub fn new_reader(data string, config ReaderConfig) &Reader {
// read reads a row from the CSV data. // read reads a row from the CSV data.
// If successful, the result holds an array of each column's data. // If successful, the result holds an array of each column's data.
pub fn (mut r Reader) read() ?[]string { pub fn (mut r Reader) read() ![]string {
l := r.read_record()? l := r.read_record()!
return l return l
} }
@ -88,7 +88,7 @@ pub fn (mut r Reader) read() ?[]string {
// } // }
// return records // return records
// } // }
fn (mut r Reader) read_line() ?string { fn (mut r Reader) read_line() !string {
// last record // last record
if r.row_pos == r.data.len { if r.row_pos == r.data.len {
return IError(&EndOfFileError{}) return IError(&EndOfFileError{})
@ -119,7 +119,7 @@ fn (mut r Reader) read_line() ?string {
return line return line
} }
fn (mut r Reader) read_record() ?[]string { fn (mut r Reader) read_record() ![]string {
if r.delimiter == r.comment { if r.delimiter == r.comment {
return IError(&CommentIsDelimiterError{}) return IError(&CommentIsDelimiterError{})
} }
@ -133,7 +133,7 @@ fn (mut r Reader) read_record() ?[]string {
mut i := -1 mut i := -1
for { for {
if need_read { if need_read {
l := r.read_line()? l := r.read_line()!
if l.len <= 0 { if l.len <= 0 {
if keep_raw { if keep_raw {
line += '\n' line += '\n'

View file

@ -28,7 +28,7 @@ pub fn new_writer(config WriterConfig) &Writer {
} }
// write writes a single record // write writes a single record
pub fn (mut w Writer) write(record []string) ?bool { pub fn (mut w Writer) write(record []string) !bool {
if !valid_delim(w.delimiter) { if !valid_delim(w.delimiter) {
return IError(&InvalidDelimiterError{}) return IError(&InvalidDelimiterError{})
} }

View file

@ -5,7 +5,7 @@ import strings
// decode converts a hex string into an array of bytes. The expected // decode converts a hex string into an array of bytes. The expected
// input format is 2 ASCII characters for each output byte. If the provided // input format is 2 ASCII characters for each output byte. If the provided
// string length is not a multiple of 2, an implicit `0` is prepended to it. // string length is not a multiple of 2, an implicit `0` is prepended to it.
pub fn decode(s string) ?[]u8 { pub fn decode(s string) ![]u8 {
mut hex_str := s mut hex_str := s
if hex_str.len >= 2 { if hex_str.len >= 2 {
if s[0] == `0` && (s[1] == `x` || s[1] == `X`) { if s[0] == `0` && (s[1] == `x` || s[1] == `X`) {
@ -15,24 +15,24 @@ pub fn decode(s string) ?[]u8 {
if hex_str.len == 0 { if hex_str.len == 0 {
return []u8{} return []u8{}
} else if hex_str.len == 1 { } else if hex_str.len == 1 {
return [char2nibble(hex_str[0])?] return [char2nibble(hex_str[0])!]
} else if hex_str.len == 2 { } else if hex_str.len == 2 {
n1 := char2nibble(hex_str[0])? n1 := char2nibble(hex_str[0])!
n0 := char2nibble(hex_str[1])? n0 := char2nibble(hex_str[1])!
return [(n1 << 4) | n0] return [(n1 << 4) | n0]
} }
// calculate the first byte depending on if hex_str.len is odd // calculate the first byte depending on if hex_str.len is odd
mut val := char2nibble(hex_str[0])? mut val := char2nibble(hex_str[0])!
if hex_str.len & 1 == 0 { if hex_str.len & 1 == 0 {
val = (val << 4) | char2nibble(hex_str[1])? val = (val << 4) | char2nibble(hex_str[1])!
} }
// set cap to hex_str.len/2 rounded up // set cap to hex_str.len/2 rounded up
mut bytes := []u8{len: 1, cap: (hex_str.len + 1) >> 1, init: val} mut bytes := []u8{len: 1, cap: (hex_str.len + 1) >> 1, init: val}
// iterate over every 2 bytes // iterate over every 2 bytes
// the start index depends on if hex_str.len is odd // the start index depends on if hex_str.len is odd
for i := 2 - (hex_str.len & 1); i < hex_str.len; i += 2 { for i := 2 - (hex_str.len & 1); i < hex_str.len; i += 2 {
n1 := char2nibble(hex_str[i])? n1 := char2nibble(hex_str[i])!
n0 := char2nibble(hex_str[i + 1])? n0 := char2nibble(hex_str[i + 1])!
bytes << (n1 << 4) | n0 bytes << (n1 << 4) | n0
} }
return bytes return bytes
@ -52,7 +52,7 @@ pub fn encode(bytes []u8) string {
} }
// char2nibble converts an ASCII hex character to it's hex value // char2nibble converts an ASCII hex character to it's hex value
fn char2nibble(b u8) ?u8 { fn char2nibble(b u8) !u8 {
match b { match b {
`0`...`9` { return b - u8(`0`) } `0`...`9` { return b - u8(`0`) }
`A`...`F` { return b - u8(`A`) + 10 } `A`...`F` { return b - u8(`A`) + 10 }

View file

@ -1,19 +1,19 @@
module hex module hex
fn test_decode() ? { fn test_decode() {
assert decode('')? == [] assert decode('')! == []
assert decode('0')? == [u8(0x0)] assert decode('0')! == [u8(0x0)]
assert decode('f')? == [u8(0xf)] assert decode('f')! == [u8(0xf)]
assert decode('0f')? == [u8(0x0f)] assert decode('0f')! == [u8(0x0f)]
assert decode('ff')? == [u8(0xff)] assert decode('ff')! == [u8(0xff)]
assert decode('123')? == [u8(0x1), 0x23] assert decode('123')! == [u8(0x1), 0x23]
assert decode('1234')? == [u8(0x12), 0x34] assert decode('1234')! == [u8(0x12), 0x34]
assert decode('12345')? == [u8(0x1), 0x23, 0x45] assert decode('12345')! == [u8(0x1), 0x23, 0x45]
assert decode('0123456789abcdef')? == [u8(0x01), 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef] assert decode('0123456789abcdef')! == [u8(0x01), 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]
assert decode('123456789ABCDEF')? == [u8(0x01), 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef] assert decode('123456789ABCDEF')! == [u8(0x01), 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]
} }
fn test_decode_fails() ? { fn test_decode_fails() ! {
if x := decode('foo') { if x := decode('foo') {
return error('expected decode to fail, got $x') return error('expected decode to fail, got $x')
} }
@ -31,24 +31,24 @@ fn test_decode_fails() ? {
} }
} }
fn test_encode() ? { fn test_encode() {
assert encode(decode('')?) == '' assert encode(decode('')!) == ''
assert encode(decode('0')?) == '00' assert encode(decode('0')!) == '00'
assert encode(decode('f')?) == '0f' assert encode(decode('f')!) == '0f'
assert encode(decode('0f')?) == '0f' assert encode(decode('0f')!) == '0f'
assert encode(decode('ff')?) == 'ff' assert encode(decode('ff')!) == 'ff'
assert encode(decode('123')?) == '0123' assert encode(decode('123')!) == '0123'
assert encode(decode('1234')?) == '1234' assert encode(decode('1234')!) == '1234'
assert encode(decode('12345')?) == '012345' assert encode(decode('12345')!) == '012345'
assert encode(decode('abcdef')?) == 'abcdef' assert encode(decode('abcdef')!) == 'abcdef'
assert encode(decode('ABCDEF')?) == 'abcdef' assert encode(decode('ABCDEF')!) == 'abcdef'
} }
fn test_decode_0x() ? { fn test_decode_0x() {
assert decode('0x')? == [] assert decode('0x')! == []
assert decode('0x0')? == [u8(0x0)] assert decode('0x0')! == [u8(0x0)]
assert decode('0X1234')? == [u8(0x12), 0x34] assert decode('0X1234')! == [u8(0x12), 0x34]
assert decode('0x12345')? == [u8(0x1), 0x23, 0x45] assert decode('0x12345')! == [u8(0x1), 0x23, 0x45]
assert decode('0x0123456789abcdef')? == [u8(0x01), 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef] assert decode('0x0123456789abcdef')! == [u8(0x01), 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]
assert decode('0X123456789ABCDEF')? == [u8(0x01), 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef] assert decode('0X123456789ABCDEF')! == [u8(0x01), 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]
} }

View file

@ -154,17 +154,17 @@ pub fn integer_from_bytes(input []u8, config IntegerConfig) Integer {
// integer_from_string creates a new `big.Integer` from the decimal digits specified in the given string. // integer_from_string creates a new `big.Integer` from the decimal digits specified in the given string.
// For other bases, use `big.integer_from_radix` instead. // For other bases, use `big.integer_from_radix` instead.
pub fn integer_from_string(characters string) ?Integer { pub fn integer_from_string(characters string) !Integer {
return integer_from_radix(characters, 10) return integer_from_radix(characters, 10)
} }
// integer_from_radix creates a new `big.Integer` from the given string and radix. // integer_from_radix creates a new `big.Integer` from the given string and radix.
pub fn integer_from_radix(all_characters string, radix u32) ?Integer { pub fn integer_from_radix(all_characters string, radix u32) !Integer {
if radix < 2 || radix > 36 { if radix < 2 || radix > 36 {
return error('Radix must be between 2 and 36 (inclusive)') return error('Radix must be between 2 and 36 (inclusive)')
} }
characters := all_characters.to_lower() characters := all_characters.to_lower()
validate_string(characters, radix)? validate_string(characters, radix)!
return match radix { return match radix {
2 { 2 {
integer_from_special_string(characters, 1) integer_from_special_string(characters, 1)
@ -179,7 +179,7 @@ pub fn integer_from_radix(all_characters string, radix u32) ?Integer {
} }
[direct_array_access] [direct_array_access]
fn validate_string(characters string, radix u32) ? { fn validate_string(characters string, radix u32) ! {
sign_present := characters[0] == `+` || characters[0] == `-` sign_present := characters[0] == `+` || characters[0] == `-`
start_index := if sign_present { 1 } else { 0 } start_index := if sign_present { 1 } else { 0 }

View file

@ -16,7 +16,7 @@ rand.seed([u32(3110), 50714])
... ...
// Use the top-level functions // Use the top-level functions
rand.u32n(100)? rand.u32n(100)!
rand.int() // among others ... rand.int() // among others ...
``` ```
@ -41,7 +41,7 @@ rng.seed(seed.time_seed_array(pcg32.seed_len))
... ...
// Use functions of your choice // Use functions of your choice
rng.u32n(100)? rng.u32n(100)!
rng.int() // among others ... rng.int() // among others ...
``` ```

View file

@ -36,7 +36,7 @@ pub:
} }
// validate_for is a helper function for validating the configuration struct for the given array. // validate_for is a helper function for validating the configuration struct for the given array.
pub fn (config ShuffleConfigStruct) validate_for<T>(a []T) ? { pub fn (config ShuffleConfigStruct) validate_for<T>(a []T) ! {
if config.start < 0 || config.start >= a.len { if config.start < 0 || config.start >= a.len {
return error("argument 'config.start' must be in range [0, a.len)") return error("argument 'config.start' must be in range [0, a.len)")
} }

View file

@ -26,7 +26,7 @@ mut:
// bytes returns a buffer of `bytes_needed` random bytes // bytes returns a buffer of `bytes_needed` random bytes
[inline] [inline]
pub fn (mut rng PRNG) bytes(bytes_needed int) ?[]u8 { pub fn (mut rng PRNG) bytes(bytes_needed int) ![]u8 {
if bytes_needed < 0 { if bytes_needed < 0 {
return error('can not read < 0 random bytes') return error('can not read < 0 random bytes')
} }
@ -44,7 +44,7 @@ pub fn (mut rng PRNG) read(mut buf []u8) {
// u32n returns a uniformly distributed pseudorandom 32-bit signed positive `u32` in range `[0, max)`. // u32n returns a uniformly distributed pseudorandom 32-bit signed positive `u32` in range `[0, max)`.
[inline] [inline]
pub fn (mut rng PRNG) u32n(max u32) ?u32 { pub fn (mut rng PRNG) u32n(max u32) !u32 {
if max == 0 { if max == 0 {
return error('max must be positive integer') return error('max must be positive integer')
} }
@ -76,7 +76,7 @@ pub fn (mut rng PRNG) u32n(max u32) ?u32 {
// u64n returns a uniformly distributed pseudorandom 64-bit signed positive `u64` in range `[0, max)`. // u64n returns a uniformly distributed pseudorandom 64-bit signed positive `u64` in range `[0, max)`.
[inline] [inline]
pub fn (mut rng PRNG) u64n(max u64) ?u64 { pub fn (mut rng PRNG) u64n(max u64) !u64 {
if max == 0 { if max == 0 {
return error('max must be positive integer') return error('max must be positive integer')
} }
@ -102,20 +102,20 @@ pub fn (mut rng PRNG) u64n(max u64) ?u64 {
// u32_in_range returns a uniformly distributed pseudorandom 32-bit unsigned `u32` in range `[min, max)`. // u32_in_range returns a uniformly distributed pseudorandom 32-bit unsigned `u32` in range `[min, max)`.
[inline] [inline]
pub fn (mut rng PRNG) u32_in_range(min u32, max u32) ?u32 { pub fn (mut rng PRNG) u32_in_range(min u32, max u32) !u32 {
if max <= min { if max <= min {
return error('max must be greater than min') return error('max must be greater than min')
} }
return min + rng.u32n(max - min)? return min + rng.u32n(max - min)!
} }
// u64_in_range returns a uniformly distributed pseudorandom 64-bit unsigned `u64` in range `[min, max)`. // u64_in_range returns a uniformly distributed pseudorandom 64-bit unsigned `u64` in range `[min, max)`.
[inline] [inline]
pub fn (mut rng PRNG) u64_in_range(min u64, max u64) ?u64 { pub fn (mut rng PRNG) u64_in_range(min u64, max u64) !u64 {
if max <= min { if max <= min {
return error('max must be greater than min') return error('max must be greater than min')
} }
return min + rng.u64n(max - min)? return min + rng.u64n(max - min)!
} }
// i8 returns a (possibly negative) pseudorandom 8-bit `i8`. // i8 returns a (possibly negative) pseudorandom 8-bit `i8`.
@ -156,39 +156,39 @@ pub fn (mut rng PRNG) int63() i64 {
// intn returns a pseudorandom `int` in range `[0, max)`. // intn returns a pseudorandom `int` in range `[0, max)`.
[inline] [inline]
pub fn (mut rng PRNG) intn(max int) ?int { pub fn (mut rng PRNG) intn(max int) !int {
if max <= 0 { if max <= 0 {
return error('max has to be positive.') return error('max has to be positive.')
} }
return int(rng.u32n(u32(max))?) return int(rng.u32n(u32(max))!)
} }
// i64n returns a pseudorandom int that lies in `[0, max)`. // i64n returns a pseudorandom int that lies in `[0, max)`.
[inline] [inline]
pub fn (mut rng PRNG) i64n(max i64) ?i64 { pub fn (mut rng PRNG) i64n(max i64) !i64 {
if max <= 0 { if max <= 0 {
return error('max has to be positive.') return error('max has to be positive.')
} }
return i64(rng.u64n(u64(max))?) return i64(rng.u64n(u64(max))!)
} }
// int_in_range returns a pseudorandom `int` in range `[min, max)`. // int_in_range returns a pseudorandom `int` in range `[min, max)`.
[inline] [inline]
pub fn (mut rng PRNG) int_in_range(min int, max int) ?int { pub fn (mut rng PRNG) int_in_range(min int, max int) !int {
if max <= min { if max <= min {
return error('max must be greater than min') return error('max must be greater than min')
} }
// This supports negative ranges like [-10, -5) because the difference is positive // This supports negative ranges like [-10, -5) because the difference is positive
return min + rng.intn(max - min)? return min + rng.intn(max - min)!
} }
// i64_in_range returns a pseudorandom `i64` in range `[min, max)`. // i64_in_range returns a pseudorandom `i64` in range `[min, max)`.
[inline] [inline]
pub fn (mut rng PRNG) i64_in_range(min i64, max i64) ?i64 { pub fn (mut rng PRNG) i64_in_range(min i64, max i64) !i64 {
if max <= min { if max <= min {
return error('max must be greater than min') return error('max must be greater than min')
} }
return min + rng.i64n(max - min)? return min + rng.i64n(max - min)!
} }
// f32 returns a pseudorandom `f32` value in range `[0, 1)`. // f32 returns a pseudorandom `f32` value in range `[0, 1)`.
@ -205,7 +205,7 @@ pub fn (mut rng PRNG) f64() f64 {
// f32n returns a pseudorandom `f32` value in range `[0, max]`. // f32n returns a pseudorandom `f32` value in range `[0, max]`.
[inline] [inline]
pub fn (mut rng PRNG) f32n(max f32) ?f32 { pub fn (mut rng PRNG) f32n(max f32) !f32 {
if max < 0 { if max < 0 {
return error('max has to be non-negative.') return error('max has to be non-negative.')
} }
@ -214,7 +214,7 @@ pub fn (mut rng PRNG) f32n(max f32) ?f32 {
// f64n returns a pseudorandom `f64` value in range `[0, max]`. // f64n returns a pseudorandom `f64` value in range `[0, max]`.
[inline] [inline]
pub fn (mut rng PRNG) f64n(max f64) ?f64 { pub fn (mut rng PRNG) f64n(max f64) !f64 {
if max < 0 { if max < 0 {
return error('max has to be non-negative.') return error('max has to be non-negative.')
} }
@ -223,20 +223,20 @@ pub fn (mut rng PRNG) f64n(max f64) ?f64 {
// f32_in_range returns a pseudorandom `f32` in range `[min, max]`. // f32_in_range returns a pseudorandom `f32` in range `[min, max]`.
[inline] [inline]
pub fn (mut rng PRNG) f32_in_range(min f32, max f32) ?f32 { pub fn (mut rng PRNG) f32_in_range(min f32, max f32) !f32 {
if max < min { if max < min {
return error('max must be greater than or equal to min') return error('max must be greater than or equal to min')
} }
return min + rng.f32n(max - min)? return min + rng.f32n(max - min)!
} }
// i64_in_range returns a pseudorandom `i64` in range `[min, max]`. // i64_in_range returns a pseudorandom `i64` in range `[min, max]`.
[inline] [inline]
pub fn (mut rng PRNG) f64_in_range(min f64, max f64) ?f64 { pub fn (mut rng PRNG) f64_in_range(min f64, max f64) !f64 {
if max < min { if max < min {
return error('max must be greater than or equal to min') return error('max must be greater than or equal to min')
} }
return min + rng.f64n(max - min)? return min + rng.f64n(max - min)!
} }
// ulid generates an Unique Lexicographically sortable IDentifier. // ulid generates an Unique Lexicographically sortable IDentifier.
@ -275,7 +275,7 @@ pub fn (mut rng PRNG) ascii(len int) string {
} }
// bernoulli returns true with a probability p. Note that 0 <= p <= 1. // bernoulli returns true with a probability p. Note that 0 <= p <= 1.
pub fn (mut rng PRNG) bernoulli(p f64) ?bool { pub fn (mut rng PRNG) bernoulli(p f64) !bool {
if p < 0 || p > 1 { if p < 0 || p > 1 {
return error('$p is not a valid probability value.') return error('$p is not a valid probability value.')
} }
@ -284,13 +284,13 @@ pub fn (mut rng PRNG) bernoulli(p f64) ?bool {
// normal returns a normally distributed pseudorandom f64 in range `[0, 1)`. // normal returns a normally distributed pseudorandom f64 in range `[0, 1)`.
// NOTE: Use normal_pair() instead if you're generating a lot of normal variates. // NOTE: Use normal_pair() instead if you're generating a lot of normal variates.
pub fn (mut rng PRNG) normal(conf config.NormalConfigStruct) ?f64 { pub fn (mut rng PRNG) normal(conf config.NormalConfigStruct) !f64 {
x, _ := rng.normal_pair(conf)? x, _ := rng.normal_pair(conf)!
return x return x
} }
// normal_pair returns a pair of normally distributed pseudorandom f64 in range `[0, 1)`. // normal_pair returns a pair of normally distributed pseudorandom f64 in range `[0, 1)`.
pub fn (mut rng PRNG) normal_pair(conf config.NormalConfigStruct) ?(f64, f64) { pub fn (mut rng PRNG) normal_pair(conf config.NormalConfigStruct) !(f64, f64) {
if conf.sigma <= 0 { if conf.sigma <= 0 {
return error('Standard deviation must be positive') return error('Standard deviation must be positive')
} }
@ -315,7 +315,7 @@ pub fn (mut rng PRNG) normal_pair(conf config.NormalConfigStruct) ?(f64, f64) {
// binomial returns the number of successful trials out of n when the // binomial returns the number of successful trials out of n when the
// probability of success for each trial is p. // probability of success for each trial is p.
pub fn (mut rng PRNG) binomial(n int, p f64) ?int { pub fn (mut rng PRNG) binomial(n int, p f64) !int {
if p < 0 || p > 1 { if p < 0 || p > 1 {
return error('$p is not a valid probability value.') return error('$p is not a valid probability value.')
} }
@ -342,8 +342,8 @@ pub fn (mut rng PRNG) exponential(lambda f64) f64 {
// optional and the entire array is shuffled by default. Leave the end as 0 to // optional and the entire array is shuffled by default. Leave the end as 0 to
// shuffle all elements until the end. // shuffle all elements until the end.
[direct_array_access] [direct_array_access]
pub fn (mut rng PRNG) shuffle<T>(mut a []T, config config.ShuffleConfigStruct) ? { pub fn (mut rng PRNG) shuffle<T>(mut a []T, config config.ShuffleConfigStruct) ! {
config.validate_for(a)? config.validate_for(a)!
new_end := if config.end == 0 { a.len } else { config.end } new_end := if config.end == 0 { a.len } else { config.end }
// We implement the Fisher-Yates shuffle: // We implement the Fisher-Yates shuffle:
@ -360,23 +360,23 @@ pub fn (mut rng PRNG) shuffle<T>(mut a []T, config config.ShuffleConfigStruct) ?
// shuffle_clone returns a random permutation of the elements in `a`. // shuffle_clone returns a random permutation of the elements in `a`.
// The permutation is done on a fresh clone of `a`, so `a` remains unchanged. // The permutation is done on a fresh clone of `a`, so `a` remains unchanged.
pub fn (mut rng PRNG) shuffle_clone<T>(a []T, config config.ShuffleConfigStruct) ?[]T { pub fn (mut rng PRNG) shuffle_clone<T>(a []T, config config.ShuffleConfigStruct) ![]T {
mut res := a.clone() mut res := a.clone()
rng.shuffle<T>(mut res, config)? rng.shuffle<T>(mut res, config)!
return res return res
} }
// choose samples k elements from the array without replacement. // choose samples k elements from the array without replacement.
// This means the indices cannot repeat and it restricts the sample size to be less than or equal to the size of the given array. // This means the indices cannot repeat and it restricts the sample size to be less than or equal to the size of the given array.
// Note that if the array has repeating elements, then the sample may have repeats as well. // Note that if the array has repeating elements, then the sample may have repeats as well.
pub fn (mut rng PRNG) choose<T>(array []T, k int) ?[]T { pub fn (mut rng PRNG) choose<T>(array []T, k int) ![]T {
n := array.len n := array.len
if k > n { if k > n {
return error('Cannot choose $k elements without replacement from a $n-element array.') return error('Cannot choose $k elements without replacement from a $n-element array.')
} }
mut results := []T{len: k} mut results := []T{len: k}
mut indices := []int{len: n, init: it} mut indices := []int{len: n, init: it}
rng.shuffle<int>(mut indices)? rng.shuffle<int>(mut indices)!
for i in 0 .. k { for i in 0 .. k {
results[i] = array[indices[i]] results[i] = array[indices[i]]
} }
@ -385,7 +385,7 @@ pub fn (mut rng PRNG) choose<T>(array []T, k int) ?[]T {
// element returns a random element from the given array. // element returns a random element from the given array.
// Note that all the positions in the array have an equal chance of being selected. This means that if the array has repeating elements, then the probability of selecting a particular element is not uniform. // Note that all the positions in the array have an equal chance of being selected. This means that if the array has repeating elements, then the probability of selecting a particular element is not uniform.
pub fn (mut rng PRNG) element<T>(array []T) ?T { pub fn (mut rng PRNG) element<T>(array []T) !T {
if array.len == 0 { if array.len == 0 {
return error('Cannot choose an element from an empty array.') return error('Cannot choose an element from an empty array.')
} }
@ -445,22 +445,22 @@ pub fn u64() u64 {
} }
// u32n returns a uniformly distributed pseudorandom 32-bit signed positive `u32` in range `[0, max)`. // u32n returns a uniformly distributed pseudorandom 32-bit signed positive `u32` in range `[0, max)`.
pub fn u32n(max u32) ?u32 { pub fn u32n(max u32) !u32 {
return default_rng.u32n(max) return default_rng.u32n(max)
} }
// u64n returns a uniformly distributed pseudorandom 64-bit signed positive `u64` in range `[0, max)`. // u64n returns a uniformly distributed pseudorandom 64-bit signed positive `u64` in range `[0, max)`.
pub fn u64n(max u64) ?u64 { pub fn u64n(max u64) !u64 {
return default_rng.u64n(max) return default_rng.u64n(max)
} }
// u32_in_range returns a uniformly distributed pseudorandom 32-bit unsigned `u32` in range `[min, max)`. // u32_in_range returns a uniformly distributed pseudorandom 32-bit unsigned `u32` in range `[min, max)`.
pub fn u32_in_range(min u32, max u32) ?u32 { pub fn u32_in_range(min u32, max u32) !u32 {
return default_rng.u32_in_range(min, max) return default_rng.u32_in_range(min, max)
} }
// u64_in_range returns a uniformly distributed pseudorandom 64-bit unsigned `u64` in range `[min, max)`. // u64_in_range returns a uniformly distributed pseudorandom 64-bit unsigned `u64` in range `[min, max)`.
pub fn u64_in_range(min u64, max u64) ?u64 { pub fn u64_in_range(min u64, max u64) !u64 {
return default_rng.u64_in_range(min, max) return default_rng.u64_in_range(min, max)
} }
@ -475,7 +475,7 @@ pub fn int() int {
} }
// intn returns a uniformly distributed pseudorandom 32-bit signed positive `int` in range `[0, max)`. // intn returns a uniformly distributed pseudorandom 32-bit signed positive `int` in range `[0, max)`.
pub fn intn(max int) ?int { pub fn intn(max int) !int {
return default_rng.intn(max) return default_rng.intn(max)
} }
@ -486,7 +486,7 @@ pub fn u8() u8 {
// int_in_range returns a uniformly distributed pseudorandom 32-bit signed int in range `[min, max)`. // int_in_range returns a uniformly distributed pseudorandom 32-bit signed int in range `[min, max)`.
// Both `min` and `max` can be negative, but we must have `min < max`. // Both `min` and `max` can be negative, but we must have `min < max`.
pub fn int_in_range(min int, max int) ?int { pub fn int_in_range(min int, max int) !int {
return default_rng.int_in_range(min, max) return default_rng.int_in_range(min, max)
} }
@ -501,12 +501,12 @@ pub fn i64() i64 {
} }
// i64n returns a uniformly distributed pseudorandom 64-bit signed positive `i64` in range `[0, max)`. // i64n returns a uniformly distributed pseudorandom 64-bit signed positive `i64` in range `[0, max)`.
pub fn i64n(max i64) ?i64 { pub fn i64n(max i64) !i64 {
return default_rng.i64n(max) return default_rng.i64n(max)
} }
// i64_in_range returns a uniformly distributed pseudorandom 64-bit signed `i64` in range `[min, max)`. // i64_in_range returns a uniformly distributed pseudorandom 64-bit signed `i64` in range `[min, max)`.
pub fn i64_in_range(min i64, max i64) ?i64 { pub fn i64_in_range(min i64, max i64) !i64 {
return default_rng.i64_in_range(min, max) return default_rng.i64_in_range(min, max)
} }
@ -526,27 +526,27 @@ pub fn f64() f64 {
} }
// f32n returns a uniformly distributed 32-bit floating point in range `[0, max)`. // f32n returns a uniformly distributed 32-bit floating point in range `[0, max)`.
pub fn f32n(max f32) ?f32 { pub fn f32n(max f32) !f32 {
return default_rng.f32n(max) return default_rng.f32n(max)
} }
// f64n returns a uniformly distributed 64-bit floating point in range `[0, max)`. // f64n returns a uniformly distributed 64-bit floating point in range `[0, max)`.
pub fn f64n(max f64) ?f64 { pub fn f64n(max f64) !f64 {
return default_rng.f64n(max) return default_rng.f64n(max)
} }
// f32_in_range returns a uniformly distributed 32-bit floating point in range `[min, max)`. // f32_in_range returns a uniformly distributed 32-bit floating point in range `[min, max)`.
pub fn f32_in_range(min f32, max f32) ?f32 { pub fn f32_in_range(min f32, max f32) !f32 {
return default_rng.f32_in_range(min, max) return default_rng.f32_in_range(min, max)
} }
// f64_in_range returns a uniformly distributed 64-bit floating point in range `[min, max)`. // f64_in_range returns a uniformly distributed 64-bit floating point in range `[min, max)`.
pub fn f64_in_range(min f64, max f64) ?f64 { pub fn f64_in_range(min f64, max f64) !f64 {
return default_rng.f64_in_range(min, max) return default_rng.f64_in_range(min, max)
} }
// bytes returns a buffer of `bytes_needed` random bytes // bytes returns a buffer of `bytes_needed` random bytes
pub fn bytes(bytes_needed int) ?[]u8 { pub fn bytes(bytes_needed int) ![]u8 {
return default_rng.bytes(bytes_needed) return default_rng.bytes(bytes_needed)
} }
@ -599,26 +599,26 @@ pub fn ascii(len int) string {
// shuffle randomly permutates the elements in `a`. The range for shuffling is // shuffle randomly permutates the elements in `a`. The range for shuffling is
// optional and the entire array is shuffled by default. Leave the end as 0 to // optional and the entire array is shuffled by default. Leave the end as 0 to
// shuffle all elements until the end. // shuffle all elements until the end.
pub fn shuffle<T>(mut a []T, config config.ShuffleConfigStruct) ? { pub fn shuffle<T>(mut a []T, config config.ShuffleConfigStruct) ! {
default_rng.shuffle<T>(mut a, config)? default_rng.shuffle<T>(mut a, config)!
} }
// shuffle_clone returns a random permutation of the elements in `a`. // shuffle_clone returns a random permutation of the elements in `a`.
// The permutation is done on a fresh clone of `a`, so `a` remains unchanged. // The permutation is done on a fresh clone of `a`, so `a` remains unchanged.
pub fn shuffle_clone<T>(a []T, config config.ShuffleConfigStruct) ?[]T { pub fn shuffle_clone<T>(a []T, config config.ShuffleConfigStruct) ![]T {
return default_rng.shuffle_clone<T>(a, config) return default_rng.shuffle_clone<T>(a, config)
} }
// choose samples k elements from the array without replacement. // choose samples k elements from the array without replacement.
// This means the indices cannot repeat and it restricts the sample size to be less than or equal to the size of the given array. // This means the indices cannot repeat and it restricts the sample size to be less than or equal to the size of the given array.
// Note that if the array has repeating elements, then the sample may have repeats as well. // Note that if the array has repeating elements, then the sample may have repeats as well.
pub fn choose<T>(array []T, k int) ?[]T { pub fn choose<T>(array []T, k int) ![]T {
return default_rng.choose<T>(array, k) return default_rng.choose<T>(array, k)
} }
// element returns a random element from the given array. // element returns a random element from the given array.
// Note that all the positions in the array have an equal chance of being selected. This means that if the array has repeating elements, then the probability of selecting a particular element is not uniform. // Note that all the positions in the array have an equal chance of being selected. This means that if the array has repeating elements, then the probability of selecting a particular element is not uniform.
pub fn element<T>(array []T) ?T { pub fn element<T>(array []T) !T {
return default_rng.element<T>(array) return default_rng.element<T>(array)
} }
@ -629,24 +629,24 @@ pub fn sample<T>(array []T, k int) []T {
} }
// bernoulli returns true with a probability p. Note that 0 <= p <= 1. // bernoulli returns true with a probability p. Note that 0 <= p <= 1.
pub fn bernoulli(p f64) ?bool { pub fn bernoulli(p f64) !bool {
return default_rng.bernoulli(p) return default_rng.bernoulli(p)
} }
// normal returns a normally distributed pseudorandom f64 in range `[0, 1)`. // normal returns a normally distributed pseudorandom f64 in range `[0, 1)`.
// NOTE: Use normal_pair() instead if you're generating a lot of normal variates. // NOTE: Use normal_pair() instead if you're generating a lot of normal variates.
pub fn normal(conf config.NormalConfigStruct) ?f64 { pub fn normal(conf config.NormalConfigStruct) !f64 {
return default_rng.normal(conf) return default_rng.normal(conf)
} }
// normal_pair returns a pair of normally distributed pseudorandom f64 in range `[0, 1)`. // normal_pair returns a pair of normally distributed pseudorandom f64 in range `[0, 1)`.
pub fn normal_pair(conf config.NormalConfigStruct) ?(f64, f64) { pub fn normal_pair(conf config.NormalConfigStruct) !(f64, f64) {
return default_rng.normal_pair(conf) return default_rng.normal_pair(conf)
} }
// binomial returns the number of successful trials out of n when the // binomial returns the number of successful trials out of n when the
// probability of success for each trial is p. // probability of success for each trial is p.
pub fn binomial(n int, p f64) ?int { pub fn binomial(n int, p f64) !int {
return default_rng.binomial(n, p) return default_rng.binomial(n, p)
} }

View file

@ -3,7 +3,7 @@ import rand
fn test_rand_bytes() { fn test_rand_bytes() {
mut randoms := []string{} mut randoms := []string{}
for i in 0 .. 100 { for i in 0 .. 100 {
x := rand.bytes(i)?.hex() x := rand.bytes(i)!.hex()
if x.len > 0 { if x.len > 0 {
randoms << x randoms << x
} }
@ -25,7 +25,7 @@ fn test_prng_rand_bytes() {
mut randoms := []string{} mut randoms := []string{}
mut rng := rand.get_current_rng() mut rng := rand.get_current_rng()
for i in 0 .. 100 { for i in 0 .. 100 {
x := rng.bytes(i)?.hex() x := rng.bytes(i)!.hex()
if x.len > 0 { if x.len > 0 {
randoms << x randoms << x
} }

View file

@ -358,11 +358,11 @@ fn test_shuffle_partial() {
mut a := [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] mut a := [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
mut b := a.clone() mut b := a.clone()
rand.shuffle(mut a, start: 4)? rand.shuffle(mut a, start: 4)!
assert a[..4] == b[..4] assert a[..4] == b[..4]
a = b.clone() a = b.clone()
rand.shuffle(mut a, start: 3, end: 7)? rand.shuffle(mut a, start: 3, end: 7)!
assert a[..3] == b[..3] assert a[..3] == b[..3]
assert a[7..] == b[7..] assert a[7..] == b[7..]
} }
@ -386,7 +386,7 @@ fn test_choose() {
lengths := [1, 3, 4, 5, 6, 7] lengths := [1, 3, 4, 5, 6, 7]
a := ['one', 'two', 'three', 'four', 'five', 'six', 'seven'] a := ['one', 'two', 'three', 'four', 'five', 'six', 'seven']
for length in lengths { for length in lengths {
b := rand.choose(a, length)? b := rand.choose(a, length)!
assert b.len == length assert b.len == length
for element in b { for element in b {
assert element in a assert element in a
@ -415,7 +415,7 @@ fn test_sample() {
fn test_element1() { fn test_element1() {
a := ['one', 'two', 'four', 'five', 'six', 'seven'] a := ['one', 'two', 'four', 'five', 'six', 'seven']
for _ in 0 .. 30 { for _ in 0 .. 30 {
e := rand.element(a)? e := rand.element(a)!
assert e in a assert e in a
assert 'three' != e assert 'three' != e
} }
@ -423,7 +423,7 @@ fn test_element1() {
fn test_element2() { fn test_element2() {
for _ in 0 .. 30 { for _ in 0 .. 30 {
e := rand.element([1, 2, 5, 6, 7, 8])? e := rand.element([1, 2, 5, 6, 7, 8])!
assert e in [1, 2, 5, 6, 7, 8] assert e in [1, 2, 5, 6, 7, 8]
assert 3 != e assert 3 != e
assert 4 != e assert 4 != e

View file

@ -23,7 +23,7 @@ struct Termios {
// an error if the line is empty. // an error if the line is empty.
// The `prompt` `string` is output as a prefix text for the input capturing. // The `prompt` `string` is output as a prefix text for the input capturing.
// read_line_utf8 is the main method of the `readline` module and `Readline` struct. // read_line_utf8 is the main method of the `readline` module and `Readline` struct.
pub fn (mut r Readline) read_line_utf8(prompt string) ?[]rune { pub fn (mut r Readline) read_line_utf8(prompt string) ![]rune {
r.current = []rune{} r.current = []rune{}
r.cursor = 0 r.cursor = 0
r.prompt = prompt r.prompt = prompt
@ -49,8 +49,8 @@ pub fn (mut r Readline) read_line_utf8(prompt string) ?[]rune {
// read_line does the same as `read_line_utf8` but returns user input as a `string`. // read_line does the same as `read_line_utf8` but returns user input as a `string`.
// (As opposed to `[]rune` returned by `read_line_utf8`). // (As opposed to `[]rune` returned by `read_line_utf8`).
pub fn (mut r Readline) read_line(prompt string) ?string { pub fn (mut r Readline) read_line(prompt string) !string {
s := r.read_line_utf8(prompt)? s := r.read_line_utf8(prompt)!
return s.string() return s.string()
} }
@ -63,9 +63,9 @@ pub fn (mut r Readline) read_line(prompt string) ?string {
// read_line_utf8 is the main method of the `readline` module and `Readline` struct. // read_line_utf8 is the main method of the `readline` module and `Readline` struct.
// NOTE that this version of `read_line_utf8` is a standalone function without // NOTE that this version of `read_line_utf8` is a standalone function without
// persistent functionalities (e.g. history). // persistent functionalities (e.g. history).
pub fn read_line_utf8(prompt string) ?[]rune { pub fn read_line_utf8(prompt string) ![]rune {
mut r := Readline{} mut r := Readline{}
s := r.read_line_utf8(prompt)? s := r.read_line_utf8(prompt)!
return s return s
} }
@ -73,8 +73,8 @@ pub fn read_line_utf8(prompt string) ?[]rune {
// (As opposed to `[]rune` as returned by `read_line_utf8`). // (As opposed to `[]rune` as returned by `read_line_utf8`).
// NOTE that this version of `read_line` is a standalone function without // NOTE that this version of `read_line` is a standalone function without
// persistent functionalities (e.g. history). // persistent functionalities (e.g. history).
pub fn read_line(prompt string) ?string { pub fn read_line(prompt string) !string {
mut r := Readline{} mut r := Readline{}
s := r.read_line(prompt)? s := r.read_line(prompt)!
return s return s
} }

View file

@ -15,7 +15,7 @@ struct Termios {}
// The `prompt` `string` is output as a prefix text for the input capturing. // The `prompt` `string` is output as a prefix text for the input capturing.
// read_line_utf8 is the main method of the `readline` module and `Readline` struct. // read_line_utf8 is the main method of the `readline` module and `Readline` struct.
pub fn (mut r Readline) read_line(prompt string) ?string { pub fn (mut r Readline) read_line(prompt string) !string {
res := '' res := ''
print(prompt) print(prompt)
#const rl = $readline.createInterface({input: $process.stdin,output: $process.stdout,prompt: prompt.str}) #const rl = $readline.createInterface({input: $process.stdin,output: $process.stdout,prompt: prompt.str})
@ -25,8 +25,8 @@ pub fn (mut r Readline) read_line(prompt string) ?string {
return res return res
} }
pub fn read_line(prompt string) ?string { pub fn read_line(prompt string) !string {
mut r := Readline{} mut r := Readline{}
s := r.read_line(prompt)? s := r.read_line(prompt)!
return s return s
} }

View file

@ -133,7 +133,7 @@ pub fn (r Readline) read_char() !int {
// an error if the line is empty. // an error if the line is empty.
// The `prompt` `string` is output as a prefix text for the input capturing. // The `prompt` `string` is output as a prefix text for the input capturing.
// read_line_utf8 is the main method of the `readline` module and `Readline` struct. // read_line_utf8 is the main method of the `readline` module and `Readline` struct.
pub fn (mut r Readline) read_line_utf8(prompt string) ?[]rune { pub fn (mut r Readline) read_line_utf8(prompt string) ![]rune {
r.current = []rune{} r.current = []rune{}
r.cursor = 0 r.cursor = 0
r.prompt = prompt r.prompt = prompt
@ -168,8 +168,8 @@ pub fn (mut r Readline) read_line_utf8(prompt string) ?[]rune {
// read_line does the same as `read_line_utf8` but returns user input as a `string`. // read_line does the same as `read_line_utf8` but returns user input as a `string`.
// (As opposed to `[]rune` returned by `read_line_utf8`). // (As opposed to `[]rune` returned by `read_line_utf8`).
pub fn (mut r Readline) read_line(prompt string) ?string { pub fn (mut r Readline) read_line(prompt string) !string {
s := r.read_line_utf8(prompt)? s := r.read_line_utf8(prompt)!
return s.string() return s.string()
} }
@ -182,9 +182,9 @@ pub fn (mut r Readline) read_line(prompt string) ?string {
// read_line_utf8 is the main method of the `readline` module and `Readline` struct. // read_line_utf8 is the main method of the `readline` module and `Readline` struct.
// NOTE that this version of `read_line_utf8` is a standalone function without // NOTE that this version of `read_line_utf8` is a standalone function without
// persistent functionalities (e.g. history). // persistent functionalities (e.g. history).
pub fn read_line_utf8(prompt string) ?[]rune { pub fn read_line_utf8(prompt string) ![]rune {
mut r := Readline{} mut r := Readline{}
s := r.read_line_utf8(prompt)? s := r.read_line_utf8(prompt)!
return s return s
} }
@ -192,9 +192,9 @@ pub fn read_line_utf8(prompt string) ?[]rune {
// (As opposed to `[]rune` as returned by `read_line_utf8`). // (As opposed to `[]rune` as returned by `read_line_utf8`).
// NOTE that this version of `read_line` is a standalone function without // NOTE that this version of `read_line` is a standalone function without
// persistent functionalities (e.g. history). // persistent functionalities (e.g. history).
pub fn read_line(prompt string) ?string { pub fn read_line(prompt string) !string {
mut r := Readline{} mut r := Readline{}
s := r.read_line(prompt)? s := r.read_line(prompt)!
return s return s
} }

View file

@ -24,7 +24,7 @@ struct Termios {
// an error if the line is empty. // an error if the line is empty.
// The `prompt` `string` is output as a prefix text for the input capturing. // The `prompt` `string` is output as a prefix text for the input capturing.
// read_line_utf8 is the main method of the `readline` module and `Readline` struct. // read_line_utf8 is the main method of the `readline` module and `Readline` struct.
pub fn (mut r Readline) read_line_utf8(prompt string) ?[]rune { pub fn (mut r Readline) read_line_utf8(prompt string) ![]rune {
r.current = []rune{} r.current = []rune{}
r.cursor = 0 r.cursor = 0
r.prompt = prompt r.prompt = prompt
@ -47,8 +47,8 @@ pub fn (mut r Readline) read_line_utf8(prompt string) ?[]rune {
// read_line does the same as `read_line_utf8` but returns user input as a `string`. // read_line does the same as `read_line_utf8` but returns user input as a `string`.
// (As opposed to `[]rune` returned by `read_line_utf8`). // (As opposed to `[]rune` returned by `read_line_utf8`).
pub fn (mut r Readline) read_line(prompt string) ?string { pub fn (mut r Readline) read_line(prompt string) !string {
s := r.read_line_utf8(prompt)? s := r.read_line_utf8(prompt)!
return s.string() return s.string()
} }
@ -61,9 +61,9 @@ pub fn (mut r Readline) read_line(prompt string) ?string {
// read_line_utf8 is the main method of the `readline` module and `Readline` struct. // read_line_utf8 is the main method of the `readline` module and `Readline` struct.
// NOTE that this version of `read_line_utf8` is a standalone function without // NOTE that this version of `read_line_utf8` is a standalone function without
// persistent functionalities (e.g. history). // persistent functionalities (e.g. history).
pub fn read_line_utf8(prompt string) ?[]rune { pub fn read_line_utf8(prompt string) ![]rune {
mut r := Readline{} mut r := Readline{}
s := r.read_line_utf8(prompt)? s := r.read_line_utf8(prompt)!
return s return s
} }
@ -71,8 +71,8 @@ pub fn read_line_utf8(prompt string) ?[]rune {
// (As opposed to `[]rune` as returned by `read_line_utf8`). // (As opposed to `[]rune` as returned by `read_line_utf8`).
// NOTE that this version of `read_line` is a standalone function without // NOTE that this version of `read_line` is a standalone function without
// persistent functionalities (e.g. history). // persistent functionalities (e.g. history).
pub fn read_line(prompt string) ?string { pub fn read_line(prompt string) !string {
mut r := Readline{} mut r := Readline{}
s := r.read_line(prompt)? s := r.read_line(prompt)!
return s return s
} }

View file

@ -2,7 +2,7 @@
module embed_file module embed_file
interface Decoder { interface Decoder {
decompress([]u8) ?[]u8 decompress([]u8) ![]u8
} }
struct EmbedFileDecoders { struct EmbedFileDecoders {

View file

@ -22,7 +22,7 @@ fn test_out_files() {
println(term.colorize(term.green, '> testing whether .out files match:')) println(term.colorize(term.green, '> testing whether .out files match:'))
os.chdir(vroot) or {} os.chdir(vroot) or {}
output_path := os.join_path(os.temp_dir(), 'v', 'coutput', 'out') output_path := os.join_path(os.temp_dir(), 'v', 'coutput', 'out')
os.mkdir_all(output_path)? os.mkdir_all(output_path)!
defer { defer {
os.rmdir_all(output_path) or {} os.rmdir_all(output_path) or {}
} }
@ -50,7 +50,7 @@ fn test_out_files() {
panic(res.output) panic(res.output)
} }
mut found := res.output.trim_right('\r\n').replace('\r\n', '\n') mut found := res.output.trim_right('\r\n').replace('\r\n', '\n')
mut expected := os.read_file(out_path)? mut expected := os.read_file(out_path)!
expected = expected.trim_right('\r\n').replace('\r\n', '\n') expected = expected.trim_right('\r\n').replace('\r\n', '\n')
if expected.contains('================ V panic ================') { if expected.contains('================ V panic ================') {
// panic include backtraces and absolute file paths, so can't do char by char comparison // panic include backtraces and absolute file paths, so can't do char by char comparison
@ -93,7 +93,7 @@ fn test_c_must_have_files() {
println(term.colorize(term.green, '> testing whether `.c.must_have` files match:')) println(term.colorize(term.green, '> testing whether `.c.must_have` files match:'))
os.chdir(vroot) or {} os.chdir(vroot) or {}
output_path := os.join_path(os.temp_dir(), 'v', 'coutput', 'c_must_have') output_path := os.join_path(os.temp_dir(), 'v', 'coutput', 'c_must_have')
os.mkdir_all(output_path)? os.mkdir_all(output_path)!
defer { defer {
os.rmdir_all(output_path) or {} os.rmdir_all(output_path) or {}
} }

View file

@ -3,7 +3,7 @@
{1, { .str=(byteptr)("embed.vv"), .len=8, .is_lit=1 }, { .str=(byteptr)("none"), .len=4, .is_lit=1 }, _v_embed_blob_1}, {1, { .str=(byteptr)("embed.vv"), .len=8, .is_lit=1 }, { .str=(byteptr)("none"), .len=4, .is_lit=1 }, _v_embed_blob_1},
VV_LOCAL_SYMBOL void v__preludes__embed_file__zlib__init(void); VV_LOCAL_SYMBOL void v__preludes__embed_file__zlib__init(void);
VV_LOCAL_SYMBOL _option_Array_u8 v__preludes__embed_file__zlib__ZLibDecoder_decompress(v__preludes__embed_file__zlib__ZLibDecoder _d1, Array_u8 data) { VV_LOCAL_SYMBOL _result_Array_u8 v__preludes__embed_file__zlib__ZLibDecoder_decompress(v__preludes__embed_file__zlib__ZLibDecoder _d1, Array_u8 data) {
= compress__zlib__decompress(data); = compress__zlib__decompress(data);
res.compressed = v__embed_file__find_index_entry_by_path((voidptr)_v_embed_file_index, _SLIT("embed.vv"), _SLIT("zlib"))->data; res.compressed = v__embed_file__find_index_entry_by_path((voidptr)_v_embed_file_index, _SLIT("embed.vv"), _SLIT("zlib"))->data;

View file

@ -5,7 +5,7 @@ import v.embed_file
struct ZLibDecoder {} struct ZLibDecoder {}
fn (_ ZLibDecoder) decompress(data []u8) ?[]u8 { fn (_ ZLibDecoder) decompress(data []u8) ![]u8 {
return zlib.decompress(data) return zlib.decompress(data)
} }

View file

@ -1,4 +1,4 @@
import compress.zlib as z import compress.zlib as z
z.compress('hello world'.bytes())? z.compress('hello world'.bytes())!
===output=== ===output===
[120, 1, 1, 11, 0, 244, 255, 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 26, 11, 4, 93] [120, 1, 1, 11, 0, 244, 255, 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 26, 11, 4, 93]