]>
Commit | Line | Data |
---|---|---|
15c0b25d AP |
1 | package cty |
2 | ||
3 | import ( | |
4 | "fmt" | |
5 | ) | |
6 | ||
7 | // PathError is a specialization of error that represents where in a | |
8 | // potentially-deep data structure an error occured, using a Path. | |
9 | type PathError struct { | |
10 | error | |
11 | Path Path | |
12 | } | |
13 | ||
14 | func errorf(path Path, f string, args ...interface{}) error { | |
15 | // We need to copy the Path because often our caller builds it by | |
16 | // continually mutating the same underlying buffer. | |
17 | sPath := make(Path, len(path)) | |
18 | copy(sPath, path) | |
19 | return PathError{ | |
20 | error: fmt.Errorf(f, args...), | |
21 | Path: sPath, | |
22 | } | |
23 | } | |
24 | ||
25 | // NewErrorf creates a new PathError for the current path by passing the | |
26 | // given format and arguments to fmt.Errorf and then wrapping the result | |
27 | // similarly to NewError. | |
28 | func (p Path) NewErrorf(f string, args ...interface{}) error { | |
29 | return errorf(p, f, args...) | |
30 | } | |
31 | ||
32 | // NewError creates a new PathError for the current path, wrapping the given | |
33 | // error. | |
34 | func (p Path) NewError(err error) error { | |
35 | // if we're being asked to wrap an existing PathError then our new | |
36 | // PathError will be the concatenation of the two paths, ensuring | |
37 | // that we still get a single flat PathError that's thus easier for | |
38 | // callers to deal with. | |
39 | perr, wrappingPath := err.(PathError) | |
40 | pathLen := len(p) | |
41 | if wrappingPath { | |
42 | pathLen = pathLen + len(perr.Path) | |
43 | } | |
44 | ||
45 | sPath := make(Path, pathLen) | |
46 | copy(sPath, p) | |
47 | if wrappingPath { | |
48 | copy(sPath[len(p):], perr.Path) | |
49 | } | |
50 | ||
51 | return PathError{ | |
52 | error: err, | |
53 | Path: sPath, | |
54 | } | |
55 | } |