@@ -128,6 +128,59 @@ func (pt Provider) IsZero() bool {
128128 return pt == Provider {}
129129}
130130
131+ // Validate returns error if the Provider representing "modern"
132+ // (Terraform 0.14+) address is not valid. Valid address implies
133+ // both valid namespace and a non-empty hostname.
134+ //
135+ // Validation makes assumptions equivalent to [ValidateProviderAddress].
136+ //
137+ // If you can guarantee [ValidateProviderAddress] was called
138+ // on the input and the [Provider] data was not mutated
139+ // you should not need to call this method.
140+ func (pt Provider ) Validate () error {
141+ if pt .IsZero () {
142+ return & ParserError {
143+ Summary : "Empty provider address" ,
144+ Detail : "Expected address composed of hostname, provider namespace and name" ,
145+ }
146+ }
147+
148+ if pt .Hostname == "" {
149+ return & ParserError {
150+ Summary : "Unknown hostname" ,
151+ Detail : "Expected hostname in the provider address to be set" ,
152+ }
153+ }
154+ if pt .Namespace == "" {
155+ return & ParserError {
156+ Summary : "Unknown provider namespace" ,
157+ Detail : "Expected provider namespace to be set" ,
158+ }
159+ }
160+ if pt .Type == "" {
161+ return & ParserError {
162+ Summary : "Unknown provider type" ,
163+ Detail : "Expected provider type to be set" ,
164+ }
165+ }
166+
167+ if ! pt .HasKnownNamespace () {
168+ return & ParserError {
169+ Summary : "Unknown provider namespace" ,
170+ Detail : `Expected FQN in the format "hostname/namespace/name"` ,
171+ }
172+ }
173+
174+ if pt .IsLegacy () {
175+ return & ParserError {
176+ Summary : "Invalid legacy provider namespace" ,
177+ Detail : `Expected FQN in the format "hostname/namespace/name"` ,
178+ }
179+ }
180+
181+ return nil
182+ }
183+
131184// HasKnownNamespace returns true if the provider namespace is known
132185// (also if it is legacy namespace)
133186func (pt Provider ) HasKnownNamespace () bool {
@@ -162,6 +215,31 @@ func (pt Provider) LessThan(other Provider) bool {
162215 }
163216}
164217
218+ // MarshalText implements encoding.TextMarshaler interface.
219+ //
220+ // It encodes the [Provider] into an FQN, equivalent to [String]
221+ // or returns an error for an invalid [Provider].
222+ func (pt Provider ) MarshalText () ([]byte , error ) {
223+ err := pt .Validate ()
224+ if err != nil {
225+ return nil , err
226+ }
227+
228+ return []byte (pt .String ()), nil
229+ }
230+
231+ // UnmarshalText implements encoding.TextUnmarshaler interface.
232+ //
233+ // It decodes a valid provider address or returns an error
234+ // using [ParseProviderSource].
235+ //
236+ // [Validate] should be called on the decoded [Provider]
237+ // if modern-style Terraform 0.14+ addresses are expected.
238+ func (pt * Provider ) UnmarshalText (text []byte ) (err error ) {
239+ * pt , err = ParseProviderSource (string (text ))
240+ return
241+ }
242+
165243// IsLegacy returns true if the provider is a legacy-style provider
166244func (pt Provider ) IsLegacy () bool {
167245 if pt .IsZero () {
@@ -182,9 +260,10 @@ func (pt Provider) Equals(other Provider) bool {
182260// terraform-config-inspect.
183261//
184262// The following are valid source string formats:
185- // name
186- // namespace/name
187- // hostname/namespace/name
263+ //
264+ // name
265+ // namespace/name
266+ // hostname/namespace/name
188267//
189268// "name"-only format is parsed as -/name (i.e. legacy namespace)
190269// requiring further identification of the namespace via Registry API
@@ -296,7 +375,7 @@ func ParseProviderSource(str string) (Provider, error) {
296375
297376// MustParseProviderSource is a wrapper around ParseProviderSource that panics if
298377// it returns an error.
299- func MustParseProviderSource (raw string ) ( Provider ) {
378+ func MustParseProviderSource (raw string ) Provider {
300379 p , err := ParseProviderSource (raw )
301380 if err != nil {
302381 panic (err )
@@ -332,7 +411,7 @@ func ValidateProviderAddress(raw string) error {
332411 }
333412 }
334413
335- if ! p .IsLegacy () {
414+ if p .IsLegacy () {
336415 return & ParserError {
337416 Summary : "Invalid legacy provider namespace" ,
338417 Detail : `Expected FQN in the format "hostname/namespace/name"` ,
0 commit comments