toptions.nim 4.0 KB

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