@@ -168,8 +168,8 @@ func Parse[M iMember[V], V Equaler[V]](e Enum[M, V], value V) *M {
168168
169169// Builder is a constructor for an [Enum].
170170//
171- // Use [Builder.Add] to add new members to the future enum
172- // and then call [Builder.Enum] to create a new [Enum] with all added members.
171+ // Use [Builder.Add] or [Builder.AddValue] to add new members to the future enum and
172+ // then call [Builder.Enum] to create a new [Enum] with all added members.
173173//
174174// Builder is useful for when you have lots of enum members, and new ones
175175// are added over time, as the project grows. In such scenario, it's easy to forget
@@ -178,11 +178,26 @@ func Parse[M iMember[V], V Equaler[V]](e Enum[M, V], value V) *M {
178178type Builder [M iMember [V ], V comparable ] struct {
179179 members []M
180180 finished bool
181+ strict bool
181182}
182183
183184// NewBuilder creates a new [Builder], a constructor for an [Enum].
184185func NewBuilder [V comparable , M iMember [V ]]() Builder [M , V ] {
185- return Builder [M , V ]{make ([]M , 0 ), false }
186+ return Builder [M , V ]{
187+ members : make ([]M , 0 ),
188+ finished : false ,
189+ strict : false ,
190+ }
191+ }
192+
193+ // NewStrictBuilder creates a new [Builder], a constructor for an [Enum], that panics
194+ // if two members share the same value.
195+ func NewStrictBuilder [V comparable , M iMember [V ]]() Builder [M , V ] {
196+ return Builder [M , V ]{
197+ members : make ([]M , 0 ),
198+ finished : false ,
199+ strict : true ,
200+ }
186201}
187202
188203// Add registers a new [Member] in the builder.
@@ -191,9 +206,29 @@ func (b *Builder[M, V]) Add(m M) M {
191206 return m
192207}
193208
209+ // AddValue registers a new [Member] in the builder.
210+ func (b * Builder [M , V ]) AddValue (v V ) M {
211+ m := M {v }
212+ b .members = append (b .members , m )
213+ return m
214+ }
215+
194216// Enum creates a new [Enum] with all members registered using [Builder.Add].
195217func (b * Builder [M , V ]) Enum () Enum [M , V ] {
196218 b .finished = true
219+ if b .strict {
220+ b .panicOnDupe ()
221+ }
197222 e := New (b .members ... )
198223 return e
199224}
225+
226+ func (b * Builder [M , V ]) panicOnDupe () {
227+ seen := make (map [M ]struct {})
228+ for _ , m := range b .members {
229+ if _ , ok := seen [m ]; ok {
230+ panic (fmt .Sprintf ("'%v' appears more than once" , m ))
231+ }
232+ seen [m ] = struct {}{}
233+ }
234+ }
0 commit comments