blob: 617b5e2212ae9a215e67f83a2696129ed0845947 [file] [log] [blame]
Don Newton379ae252019-04-01 12:17:06 -04001// Copyright (C) MongoDB, Inc. 2017-present.
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may
4// not use this file except in compliance with the License. You may obtain
5// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
7package bsonrw
8
9import (
10 "fmt"
11)
12
13type mode int
14
15const (
16 _ mode = iota
17 mTopLevel
18 mDocument
19 mArray
20 mValue
21 mElement
22 mCodeWithScope
23 mSpacer
24)
25
26func (m mode) String() string {
27 var str string
28
29 switch m {
30 case mTopLevel:
31 str = "TopLevel"
32 case mDocument:
33 str = "DocumentMode"
34 case mArray:
35 str = "ArrayMode"
36 case mValue:
37 str = "ValueMode"
38 case mElement:
39 str = "ElementMode"
40 case mCodeWithScope:
41 str = "CodeWithScopeMode"
42 case mSpacer:
43 str = "CodeWithScopeSpacerFrame"
44 default:
45 str = "UnknownMode"
46 }
47
48 return str
49}
50
51func (m mode) TypeString() string {
52 var str string
53
54 switch m {
55 case mTopLevel:
56 str = "TopLevel"
57 case mDocument:
58 str = "Document"
59 case mArray:
60 str = "Array"
61 case mValue:
62 str = "Value"
63 case mElement:
64 str = "Element"
65 case mCodeWithScope:
66 str = "CodeWithScope"
67 case mSpacer:
68 str = "CodeWithScopeSpacer"
69 default:
70 str = "Unknown"
71 }
72
73 return str
74}
75
76// TransitionError is an error returned when an invalid progressing a
77// ValueReader or ValueWriter state machine occurs.
78// If read is false, the error is for writing
79type TransitionError struct {
80 name string
81 parent mode
82 current mode
83 destination mode
84 modes []mode
85 action string
86}
87
88func (te TransitionError) Error() string {
89 errString := fmt.Sprintf("%s can only %s", te.name, te.action)
90 if te.destination != mode(0) {
91 errString = fmt.Sprintf("%s a %s", errString, te.destination.TypeString())
92 }
93 errString = fmt.Sprintf("%s while positioned on a", errString)
94 for ind, m := range te.modes {
95 if ind != 0 && len(te.modes) > 2 {
96 errString = fmt.Sprintf("%s,", errString)
97 }
98 if ind == len(te.modes)-1 && len(te.modes) > 1 {
99 errString = fmt.Sprintf("%s or", errString)
100 }
101 errString = fmt.Sprintf("%s %s", errString, m.TypeString())
102 }
103 errString = fmt.Sprintf("%s but is positioned on a %s", errString, te.current.TypeString())
104 if te.parent != mode(0) {
105 errString = fmt.Sprintf("%s with parent %s", errString, te.parent.TypeString())
106 }
107 return errString
108}