forked from lfr/FSharp.Domain.Validation
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Text.fs
71 lines (56 loc) · 2.46 KB
/
Text.fs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
namespace FSharp.ValidationBlocks.Example
open FSharp.ValidationBlocks
open System.Text.RegularExpressions
open FSharp.ValidationBlocks.Operators
/// Define all the possible errors that the blocks can yield
type TextError =
| ContainsControlCharacters
| ContainsTabs
| ExceedsMaximumLength of int
| IsMissingOrBlank
/// This interface in not strictly necessary but it makes type declarations
/// and function signatures a lot more readable
type IText = inherit IBlock<string, TextError>
/// This is a good place to define IText-specific functions
module Text =
/// Validates the given trimmed string treating null/blank as a valid result of None
/// Use: Block.optional<Tweet> "hello!" or Block.optional "hello!"
let optional<'block when 'block :> IText> s : Result<'block option, TextError list> =
if System.String.IsNullOrWhiteSpace s then Ok None
else Block.validate<'block> s |> Result.map Some
/// Single or multi-line text without any validation
type FreeText = private FreeText of string with
interface IText with
member _.Validate =
// System.String.IsNullOrWhiteSpace => IsMissingOrBlank
fun s ->
[if s |> System.String.IsNullOrWhiteSpace then IsMissingOrBlank]
/// Single line of text (no control characters)
type Text = private Text of FreeText with
interface IText with
member _.Validate =
fun s ->
[if s |> Regex("\p{C}").IsMatch then ContainsControlCharacters]
/// Text restricted to 280 characters at most when trimmed
/// (the current maximum length of a tweeet), without tabs
type Tweet = private Tweet of FreeText with
interface IText with
member _.Validate =
fun s ->
[
if s.Contains('\t') then ContainsTabs
if s.Length > 280 then ExceedsMaximumLength 280
]
// Alternative type definition using operators (for single condition)
type FreeText' = private FreeText' of string with
interface IText with
member _.Validate =
System.String.IsNullOrWhiteSpace ==> IsMissingOrBlank
// Alternative type definition using operators (for multiple conditions)
type Tweet' = private Tweet' of FreeText with
interface IText with
member _.Validate =
fun s -> !? [
s.Contains('\t') => ContainsTabs
s.Length > 280 => ExceedsMaximumLength 280
]