/*
Copyright (c) 2025 WuJingrun(吴京润)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package f_base
import std.unicode.{UnicodeRuneExtension, UnicodeStringExtension}
public class Options<T, R> {
private init() {}
public static func isEmpty(current: Option<T>): Bool {
match (current) {
case Option<T>.None => return true
case Some(x) where x is Unit => true
case Some(x) where x is Collection<R> => (x as Collection<R>).getOrThrow().isEmpty()
case Some(_) => false
}
}
public static func isNotEmpty(current: Option<T>): Bool {
!isEmpty(current)
}
public static func isEmptyOrUnit(current: Option<T>): Bool {
isEmpty(current) || match (current) {
case Some(v) => v is Unit
case Option<T>.None => true
}
}
public static func isNotEmptyOrUnit(current: Option<T>): Bool {
!isEmptyOrUnit(current)
}
public static func isEmptyOrZero(current: Option<T>): Bool {
isEmpty(current) || match (current) {
case Some(v) => match (v) {
case x: Int64 where x == 0 => true
case x: UInt64 where x == 0 => true
case x: Int32 where x == 0 => true
case x: UInt32 where x == 0 => true
case x: Int16 where x == 0 => true
case x: UInt16 where x == 0 => true
case x: Int8 where x == 0 => true
case x: UInt8 where x == 0 => true
case x: Float64 where x == 0.0 => true
case x: Float32 where x == 0.0 => true
case x: Float16 where x == 0.0 => true
case x: Rune where x == r'\0' => true
case x: String where x.isEmpty() || x == '\0' => true
case _ => false
}
case Option<T>.None => true
}
}
public static func isNotEmptyOrZero(current: Option<T>): Bool {
!isEmptyOrZero(current)
}
public static func isEmptyOrBlank(current: Option<T>): Bool {
func isBlankRune(c: Rune) {
c == r'\0' || c.isWhiteSpace()
}
isEmpty(current) || match (current.getOrThrow()) {
case v: String => v.isBlank()
case v: Iterable<Rune> =>
for (c in v where !isBlankRune(c)) {
return false
}
true
case v: Rune => isBlankRune(v)
case _ => false
}
}
public static func isNotEmptyOrBlank(current: Option<T>): Bool {
!isEmptyOrBlank(current)
}
public static func isEmptyOrZeroOrBlank(current: Option<T>) {
isEmptyOrZero(current) || isEmptyOrBlank(current)
}
public static func isNotEmptyOrZeroOrBlank(current: Option<T>) {
!isEmptyOrZeroOrBlank(current)
}
public static func convert(origin: Option<T>, default: R, converter: (T) -> Option<R>): R {
convert(origin, converter) ?? default
}
public static func convert(origin: Option<T>, default: R): Option<R> {
convert(origin) ?? default
}
public static func convert(origin: Option<T>): Option<R> {
doConvert(origin, false)
}
public static func convertOrThrow(origin: Option<T>, default: R): Option<R> {
convertOrThrow(origin) ?? default
}
public static func convertOrThrow(origin: Option<T>): Option<R> {
doConvert(origin, true)
}
private static func doConvert(origin: Option<T>, toThrow: Bool): Option<R> {
doConvert(origin, {v => v as R}, toThrow)
}
public static func convert(origin: Option<T>, converter: (T) -> Option<R>): Option<R> {
doConvert(origin, converter, false)
}
public static func convertOrThrow(origin: Option<T>, converter: (T) -> Option<R>) {
doConvert(origin, converter, true)
}
private static func doConvert(origin: Option<T>, converter: (T) -> Option<R>, toThrow: Bool): Option<R> {
if (let Some(v) <- origin) {
if(let Some(r) <- converter(v)){
r
}else if(toThrow){
throw IllegalArgumentException()
}else{
None<R>
}
} else {
None<R>
}
}
}