mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
all: change optional to result in most of the libraries (#16123)
This commit is contained in:
@ -16,7 +16,7 @@ rand.seed([u32(3110), 50714])
|
||||
...
|
||||
|
||||
// Use the top-level functions
|
||||
rand.u32n(100)?
|
||||
rand.u32n(100)!
|
||||
rand.int() // among others ...
|
||||
```
|
||||
|
||||
@ -41,7 +41,7 @@ rng.seed(seed.time_seed_array(pcg32.seed_len))
|
||||
...
|
||||
|
||||
// Use functions of your choice
|
||||
rng.u32n(100)?
|
||||
rng.u32n(100)!
|
||||
rng.int() // among others ...
|
||||
```
|
||||
|
||||
|
@ -36,7 +36,7 @@ pub:
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return error("argument 'config.start' must be in range [0, a.len)")
|
||||
}
|
||||
|
110
vlib/rand/rand.v
110
vlib/rand/rand.v
@ -26,7 +26,7 @@ mut:
|
||||
|
||||
// bytes returns a buffer of `bytes_needed` random bytes
|
||||
[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 {
|
||||
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)`.
|
||||
[inline]
|
||||
pub fn (mut rng PRNG) u32n(max u32) ?u32 {
|
||||
pub fn (mut rng PRNG) u32n(max u32) !u32 {
|
||||
if max == 0 {
|
||||
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)`.
|
||||
[inline]
|
||||
pub fn (mut rng PRNG) u64n(max u64) ?u64 {
|
||||
pub fn (mut rng PRNG) u64n(max u64) !u64 {
|
||||
if max == 0 {
|
||||
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)`.
|
||||
[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 {
|
||||
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)`.
|
||||
[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 {
|
||||
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`.
|
||||
@ -156,39 +156,39 @@ pub fn (mut rng PRNG) int63() i64 {
|
||||
|
||||
// intn returns a pseudorandom `int` in range `[0, max)`.
|
||||
[inline]
|
||||
pub fn (mut rng PRNG) intn(max int) ?int {
|
||||
pub fn (mut rng PRNG) intn(max int) !int {
|
||||
if max <= 0 {
|
||||
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)`.
|
||||
[inline]
|
||||
pub fn (mut rng PRNG) i64n(max i64) ?i64 {
|
||||
pub fn (mut rng PRNG) i64n(max i64) !i64 {
|
||||
if max <= 0 {
|
||||
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)`.
|
||||
[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 {
|
||||
return error('max must be greater than min')
|
||||
}
|
||||
// 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)`.
|
||||
[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 {
|
||||
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)`.
|
||||
@ -205,7 +205,7 @@ pub fn (mut rng PRNG) f64() f64 {
|
||||
|
||||
// f32n returns a pseudorandom `f32` value in range `[0, max]`.
|
||||
[inline]
|
||||
pub fn (mut rng PRNG) f32n(max f32) ?f32 {
|
||||
pub fn (mut rng PRNG) f32n(max f32) !f32 {
|
||||
if max < 0 {
|
||||
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]`.
|
||||
[inline]
|
||||
pub fn (mut rng PRNG) f64n(max f64) ?f64 {
|
||||
pub fn (mut rng PRNG) f64n(max f64) !f64 {
|
||||
if max < 0 {
|
||||
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]`.
|
||||
[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 {
|
||||
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]`.
|
||||
[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 {
|
||||
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.
|
||||
@ -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.
|
||||
pub fn (mut rng PRNG) bernoulli(p f64) ?bool {
|
||||
pub fn (mut rng PRNG) bernoulli(p f64) !bool {
|
||||
if p < 0 || p > 1 {
|
||||
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)`.
|
||||
// NOTE: Use normal_pair() instead if you're generating a lot of normal variates.
|
||||
pub fn (mut rng PRNG) normal(conf config.NormalConfigStruct) ?f64 {
|
||||
x, _ := rng.normal_pair(conf)?
|
||||
pub fn (mut rng PRNG) normal(conf config.NormalConfigStruct) !f64 {
|
||||
x, _ := rng.normal_pair(conf)!
|
||||
return x
|
||||
}
|
||||
|
||||
// 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 {
|
||||
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
|
||||
// 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 {
|
||||
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
|
||||
// shuffle all elements until the end.
|
||||
[direct_array_access]
|
||||
pub fn (mut rng PRNG) shuffle<T>(mut a []T, config config.ShuffleConfigStruct) ? {
|
||||
config.validate_for(a)?
|
||||
pub fn (mut rng PRNG) shuffle<T>(mut a []T, config config.ShuffleConfigStruct) ! {
|
||||
config.validate_for(a)!
|
||||
new_end := if config.end == 0 { a.len } else { config.end }
|
||||
|
||||
// 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`.
|
||||
// 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()
|
||||
rng.shuffle<T>(mut res, config)?
|
||||
rng.shuffle<T>(mut res, config)!
|
||||
return res
|
||||
}
|
||||
|
||||
// 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.
|
||||
// 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
|
||||
if k > n {
|
||||
return error('Cannot choose $k elements without replacement from a $n-element array.')
|
||||
}
|
||||
mut results := []T{len: k}
|
||||
mut indices := []int{len: n, init: it}
|
||||
rng.shuffle<int>(mut indices)?
|
||||
rng.shuffle<int>(mut indices)!
|
||||
for i in 0 .. k {
|
||||
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.
|
||||
// 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 {
|
||||
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)`.
|
||||
pub fn u32n(max u32) ?u32 {
|
||||
pub fn u32n(max u32) !u32 {
|
||||
return default_rng.u32n(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)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
@ -475,7 +475,7 @@ pub fn int() int {
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
@ -486,7 +486,7 @@ pub fn u8() u8 {
|
||||
|
||||
// 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`.
|
||||
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)
|
||||
}
|
||||
|
||||
@ -501,12 +501,12 @@ pub fn i64() i64 {
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
@ -526,27 +526,27 @@ pub fn f64() f64 {
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
@ -599,26 +599,26 @@ pub fn ascii(len int) string {
|
||||
// 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
|
||||
// shuffle all elements until the end.
|
||||
pub fn shuffle<T>(mut a []T, config config.ShuffleConfigStruct) ? {
|
||||
default_rng.shuffle<T>(mut a, config)?
|
||||
pub fn shuffle<T>(mut a []T, config config.ShuffleConfigStruct) ! {
|
||||
default_rng.shuffle<T>(mut a, config)!
|
||||
}
|
||||
|
||||
// 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.
|
||||
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)
|
||||
}
|
||||
|
||||
// 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.
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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.
|
||||
pub fn element<T>(array []T) ?T {
|
||||
pub fn element<T>(array []T) !T {
|
||||
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.
|
||||
pub fn bernoulli(p f64) ?bool {
|
||||
pub fn bernoulli(p f64) !bool {
|
||||
return default_rng.bernoulli(p)
|
||||
}
|
||||
|
||||
// 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.
|
||||
pub fn normal(conf config.NormalConfigStruct) ?f64 {
|
||||
pub fn normal(conf config.NormalConfigStruct) !f64 {
|
||||
return default_rng.normal(conf)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// binomial returns the number of successful trials out of n when the
|
||||
// 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)
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@ import rand
|
||||
fn test_rand_bytes() {
|
||||
mut randoms := []string{}
|
||||
for i in 0 .. 100 {
|
||||
x := rand.bytes(i)?.hex()
|
||||
x := rand.bytes(i)!.hex()
|
||||
if x.len > 0 {
|
||||
randoms << x
|
||||
}
|
||||
@ -25,7 +25,7 @@ fn test_prng_rand_bytes() {
|
||||
mut randoms := []string{}
|
||||
mut rng := rand.get_current_rng()
|
||||
for i in 0 .. 100 {
|
||||
x := rng.bytes(i)?.hex()
|
||||
x := rng.bytes(i)!.hex()
|
||||
if x.len > 0 {
|
||||
randoms << x
|
||||
}
|
||||
|
@ -358,11 +358,11 @@ fn test_shuffle_partial() {
|
||||
mut a := [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
mut b := a.clone()
|
||||
|
||||
rand.shuffle(mut a, start: 4)?
|
||||
rand.shuffle(mut a, start: 4)!
|
||||
assert a[..4] == b[..4]
|
||||
|
||||
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[7..] == b[7..]
|
||||
}
|
||||
@ -386,7 +386,7 @@ fn test_choose() {
|
||||
lengths := [1, 3, 4, 5, 6, 7]
|
||||
a := ['one', 'two', 'three', 'four', 'five', 'six', 'seven']
|
||||
for length in lengths {
|
||||
b := rand.choose(a, length)?
|
||||
b := rand.choose(a, length)!
|
||||
assert b.len == length
|
||||
for element in b {
|
||||
assert element in a
|
||||
@ -415,7 +415,7 @@ fn test_sample() {
|
||||
fn test_element1() {
|
||||
a := ['one', 'two', 'four', 'five', 'six', 'seven']
|
||||
for _ in 0 .. 30 {
|
||||
e := rand.element(a)?
|
||||
e := rand.element(a)!
|
||||
assert e in a
|
||||
assert 'three' != e
|
||||
}
|
||||
@ -423,7 +423,7 @@ fn test_element1() {
|
||||
|
||||
fn test_element2() {
|
||||
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 3 != e
|
||||
assert 4 != e
|
||||
|
Reference in New Issue
Block a user