| 
									
										
										
										
											2021-11-13 12:29:08 +01:00
										 |  |  | package errors | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2021-12-12 15:47:51 +01:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2021-11-13 12:29:08 +01:00
										 |  |  | 	"sync" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-16 18:52:30 +01:00
										 |  |  | 	"codeberg.org/gruf/go-format" | 
					
						
							| 
									
										
										
										
											2021-11-13 12:29:08 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-27 15:26:58 +01:00
										 |  |  | // KV is a structure for setting key-value pairs in ErrorData. | 
					
						
							| 
									
										
										
										
											2021-11-13 12:29:08 +01:00
										 |  |  | type KV struct { | 
					
						
							|  |  |  | 	Key   string | 
					
						
							|  |  |  | 	Value interface{} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ErrorData defines a way to set and access contextual error data. | 
					
						
							| 
									
										
										
										
											2021-11-27 15:26:58 +01:00
										 |  |  | // The default implementation of this is thread-safe. | 
					
						
							| 
									
										
										
										
											2021-11-13 12:29:08 +01:00
										 |  |  | type ErrorData interface { | 
					
						
							|  |  |  | 	// Value will attempt to fetch value for given key in ErrorData | 
					
						
							|  |  |  | 	Value(string) (interface{}, bool) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Append adds the supplied key-values to ErrorData, similar keys DO overwrite | 
					
						
							|  |  |  | 	Append(...KV) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-12 15:47:51 +01:00
										 |  |  | 	// Implement byte slice representation formatter. | 
					
						
							| 
									
										
										
										
											2022-01-16 18:52:30 +01:00
										 |  |  | 	format.Formattable | 
					
						
							| 
									
										
										
										
											2021-12-12 15:47:51 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Implement string representation formatter. | 
					
						
							|  |  |  | 	fmt.Stringer | 
					
						
							| 
									
										
										
										
											2021-11-13 12:29:08 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-27 15:26:58 +01:00
										 |  |  | // NewData returns a new ErrorData implementation. | 
					
						
							| 
									
										
										
										
											2021-11-13 12:29:08 +01:00
										 |  |  | func NewData() ErrorData { | 
					
						
							|  |  |  | 	return &errorData{ | 
					
						
							| 
									
										
										
										
											2021-12-12 15:47:51 +01:00
										 |  |  | 		data: make([]KV, 0, 10), | 
					
						
							| 
									
										
										
										
											2021-11-13 12:29:08 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // errorData is our ErrorData implementation, this is essentially | 
					
						
							| 
									
										
										
										
											2021-11-27 15:26:58 +01:00
										 |  |  | // just a thread-safe string-interface map implementation. | 
					
						
							| 
									
										
										
										
											2021-11-13 12:29:08 +01:00
										 |  |  | type errorData struct { | 
					
						
							| 
									
										
										
										
											2021-12-12 15:47:51 +01:00
										 |  |  | 	data []KV | 
					
						
							| 
									
										
										
										
											2021-11-13 12:29:08 +01:00
										 |  |  | 	mu   sync.Mutex | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-12 15:47:51 +01:00
										 |  |  | func (d *errorData) set(key string, value interface{}) { | 
					
						
							|  |  |  | 	for i := range d.data { | 
					
						
							|  |  |  | 		if d.data[i].Key == key { | 
					
						
							|  |  |  | 			// Found existing, update! | 
					
						
							|  |  |  | 			d.data[i].Value = value | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Add new KV entry to slice | 
					
						
							|  |  |  | 	d.data = append(d.data, KV{ | 
					
						
							|  |  |  | 		Key:   key, | 
					
						
							|  |  |  | 		Value: value, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-13 12:29:08 +01:00
										 |  |  | func (d *errorData) Value(key string) (interface{}, bool) { | 
					
						
							|  |  |  | 	d.mu.Lock() | 
					
						
							| 
									
										
										
										
											2021-12-12 15:47:51 +01:00
										 |  |  | 	for i := range d.data { | 
					
						
							|  |  |  | 		if d.data[i].Key == key { | 
					
						
							|  |  |  | 			v := d.data[i].Value | 
					
						
							|  |  |  | 			d.mu.Unlock() | 
					
						
							|  |  |  | 			return v, true | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-11-13 12:29:08 +01:00
										 |  |  | 	d.mu.Unlock() | 
					
						
							| 
									
										
										
										
											2021-12-12 15:47:51 +01:00
										 |  |  | 	return nil, false | 
					
						
							| 
									
										
										
										
											2021-11-13 12:29:08 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (d *errorData) Append(kvs ...KV) { | 
					
						
							|  |  |  | 	d.mu.Lock() | 
					
						
							|  |  |  | 	for i := range kvs { | 
					
						
							| 
									
										
										
										
											2021-12-12 15:47:51 +01:00
										 |  |  | 		d.set(kvs[i].Key, kvs[i].Value) | 
					
						
							| 
									
										
										
										
											2021-11-13 12:29:08 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	d.mu.Unlock() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-12 15:47:51 +01:00
										 |  |  | func (d *errorData) AppendFormat(b []byte) []byte { | 
					
						
							| 
									
										
										
										
											2022-01-16 18:52:30 +01:00
										 |  |  | 	buf := format.Buffer{B: b} | 
					
						
							| 
									
										
										
										
											2021-11-13 12:29:08 +01:00
										 |  |  | 	d.mu.Lock() | 
					
						
							| 
									
										
										
										
											2021-12-12 15:47:51 +01:00
										 |  |  | 	buf.B = append(buf.B, '{') | 
					
						
							| 
									
										
										
										
											2022-01-16 18:52:30 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Append data as kv pairs | 
					
						
							| 
									
										
										
										
											2021-12-12 15:47:51 +01:00
										 |  |  | 	for i := range d.data { | 
					
						
							| 
									
										
										
										
											2022-01-16 18:52:30 +01:00
										 |  |  | 		key := d.data[i].Key | 
					
						
							|  |  |  | 		val := d.data[i].Value | 
					
						
							|  |  |  | 		format.Appendf(&buf, "{:k}={:v} ", key, val) | 
					
						
							| 
									
										
										
										
											2021-12-12 15:47:51 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-01-16 18:52:30 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Drop trailing space | 
					
						
							|  |  |  | 	if len(d.data) > 0 { | 
					
						
							|  |  |  | 		buf.Truncate(1) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-12 15:47:51 +01:00
										 |  |  | 	buf.B = append(buf.B, '}') | 
					
						
							| 
									
										
										
										
											2021-11-13 12:29:08 +01:00
										 |  |  | 	d.mu.Unlock() | 
					
						
							| 
									
										
										
										
											2021-12-12 15:47:51 +01:00
										 |  |  | 	return buf.B | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (d *errorData) String() string { | 
					
						
							|  |  |  | 	return string(d.AppendFormat(nil)) | 
					
						
							| 
									
										
										
										
											2021-11-13 12:29:08 +01:00
										 |  |  | } |