toptions.nim 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. discard """
  2. targets: "c js"
  3. """
  4. import std/[json, options]
  5. # RefPerson is used to test that overloaded `==` operator is not called by
  6. # options. It is defined here in the global scope, because otherwise the test
  7. # will not even consider the `==` operator. Different bug?
  8. type RefPerson = ref object
  9. name: string
  10. proc `==`(a, b: RefPerson): bool =
  11. assert(not a.isNil and not b.isNil)
  12. a.name == b.name
  13. template disableJsVm(body) =
  14. # something doesn't work in JS VM
  15. when defined(js):
  16. when nimvm: discard
  17. else: body
  18. else:
  19. body
  20. proc main() =
  21. type
  22. Foo = ref object
  23. test: string
  24. Test = object
  25. foo: Option[Foo]
  26. let js = """{"foo": {"test": "123"}}"""
  27. let parsed = parseJson(js)
  28. let a = parsed.to(Test)
  29. doAssert $(%*a) == """{"foo":{"test":"123"}}"""
  30. block options:
  31. # work around a bug in unittest
  32. let intNone = none(int)
  33. let stringNone = none(string)
  34. block example:
  35. proc find(haystack: string, needle: char): Option[int] =
  36. for i, c in haystack:
  37. if c == needle:
  38. return some i
  39. doAssert("abc".find('c').get() == 2)
  40. let result = "team".find('i')
  41. doAssert result == intNone
  42. doAssert result.isNone
  43. block some:
  44. doAssert some(6).get() == 6
  45. doAssert some("a").unsafeGet() == "a"
  46. doAssert some(6).isSome
  47. doAssert some("a").isSome
  48. block none:
  49. doAssertRaises UnpackDefect:
  50. discard none(int).get()
  51. doAssert(none(int).isNone)
  52. doAssert(not none(string).isSome)
  53. block equality:
  54. doAssert some("a") == some("a")
  55. doAssert some(7) != some(6)
  56. doAssert some("a") != stringNone
  57. doAssert intNone == intNone
  58. when compiles(some("a") == some(5)):
  59. doAssert false
  60. when compiles(none(string) == none(int)):
  61. doAssert false
  62. block get_with_a_default_value:
  63. doAssert(some("Correct").get("Wrong") == "Correct")
  64. doAssert(stringNone.get("Correct") == "Correct")
  65. block stringify:
  66. doAssert($(some("Correct")) == "some(\"Correct\")")
  67. doAssert($(stringNone) == "none(string)")
  68. disableJsVm:
  69. block map_with_a_void_result:
  70. var procRan = 0
  71. # TODO closure anonymous functions doesn't work in VM with JS
  72. # Error: cannot evaluate at compile time: procRan
  73. some(123).map(proc (v: int) = procRan = v)
  74. doAssert procRan == 123
  75. intNone.map(proc (v: int) = doAssert false)
  76. block map:
  77. doAssert(some(123).map(proc (v: int): int = v * 2) == some(246))
  78. doAssert(intNone.map(proc (v: int): int = v * 2).isNone)
  79. block filter:
  80. doAssert(some(123).filter(proc (v: int): bool = v == 123) == some(123))
  81. doAssert(some(456).filter(proc (v: int): bool = v == 123).isNone)
  82. doAssert(intNone.filter(proc (v: int): bool = doAssert false).isNone)
  83. block flatMap:
  84. proc addOneIfNotZero(v: int): Option[int] =
  85. if v != 0:
  86. result = some(v + 1)
  87. else:
  88. result = none(int)
  89. doAssert(some(1).flatMap(addOneIfNotZero) == some(2))
  90. doAssert(some(0).flatMap(addOneIfNotZero) == none(int))
  91. doAssert(some(1).flatMap(addOneIfNotZero).flatMap(addOneIfNotZero) == some(3))
  92. proc maybeToString(v: int): Option[string] =
  93. if v != 0:
  94. result = some($v)
  95. else:
  96. result = none(string)
  97. doAssert(some(1).flatMap(maybeToString) == some("1"))
  98. proc maybeExclaim(v: string): Option[string] =
  99. if v != "":
  100. result = some v & "!"
  101. else:
  102. result = none(string)
  103. doAssert(some(1).flatMap(maybeToString).flatMap(maybeExclaim) == some("1!"))
  104. doAssert(some(0).flatMap(maybeToString).flatMap(maybeExclaim) == none(string))
  105. block SomePointer:
  106. var intref: ref int
  107. doAssert(option(intref).isNone)
  108. intref.new
  109. doAssert(option(intref).isSome)
  110. let tmp = option(intref)
  111. doAssert(sizeof(tmp) == sizeof(ptr int))
  112. var prc = proc (x: int): int = x + 1
  113. doAssert(option(prc).isSome)
  114. prc = nil
  115. doAssert(option(prc).isNone)
  116. block:
  117. doAssert(none[int]().isNone)
  118. doAssert(none(int) == none[int]())
  119. # "$ on typed with .name"
  120. block:
  121. type Named = object
  122. name: string
  123. let nobody = none(Named)
  124. doAssert($nobody == "none(Named)")
  125. # "$ on type with name()"
  126. block:
  127. type Person = object
  128. myname: string
  129. let noperson = none(Person)
  130. doAssert($noperson == "none(Person)")
  131. # "Ref type with overloaded `==`"
  132. block:
  133. let p = some(RefPerson.new())
  134. doAssert p.isSome
  135. block: # test cstring
  136. block:
  137. let x = some("".cstring)
  138. doAssert x.isSome
  139. doAssert x.get == ""
  140. block:
  141. let x = some("12345".cstring)
  142. doAssert x.isSome
  143. doAssert x.get == "12345"
  144. block:
  145. let x = "12345".cstring
  146. let y = some(x)
  147. doAssert y.isSome
  148. doAssert y.get == "12345"
  149. block:
  150. let x = none(cstring)
  151. doAssert x.isNone
  152. doAssert $x == "none(cstring)"
  153. static: main()
  154. main()