github.com/drone/go-convert@v0.0.0-20240307072510-6bd371c65e61/convert/circle/yaml/logical.go (about)

     1  // Copyright 2022 Harness, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package yaml
    16  
    17  import "errors"
    18  
    19  type (
    20  	Matches struct {
    21  		Pattern string `yaml:"pattern,omitempty"`
    22  		Value   string `yaml:"value,omitempty"`
    23  	}
    24  
    25  	Logical struct {
    26  		Literal interface{}
    27  
    28  		And     []*Logical
    29  		Equal   []interface{}
    30  		Matches *Matches
    31  		Not     *Logical
    32  		Or      []*Logical
    33  	}
    34  
    35  	logical struct {
    36  		And     []*Logical    `yaml:"and,omitempty"`
    37  		Equal   []interface{} `yaml:"equal,omitempty"`
    38  		Matches *Matches      `yaml:"matches,omitempty"`
    39  		Not     *Logical      `yaml:"not,omitempty"`
    40  		Or      []*Logical    `yaml:"or,omitempty"`
    41  	}
    42  )
    43  
    44  // UnmarshalYAML implements the unmarshal interface.
    45  func (v *Logical) UnmarshalYAML(unmarshal func(interface{}) error) error {
    46  	var out1 *logical
    47  	var out2 interface{}
    48  
    49  	if err := unmarshal(&out1); err == nil {
    50  		v.And = out1.And
    51  		v.Equal = out1.Equal
    52  		v.Matches = out1.Matches
    53  		v.Not = out1.Not
    54  		v.Or = out1.Or
    55  
    56  		// if the struct is empty, the user probably
    57  		// assigned a yaml anchor
    58  		//
    59  		// wtf. yes this is really possible.
    60  		if !v.IsEmpty() {
    61  			return nil
    62  		}
    63  	}
    64  
    65  	if err := unmarshal(&out2); err == nil {
    66  		v.Literal = out2
    67  		return nil
    68  	}
    69  
    70  	return errors.New("failed to unmarshal logical condition")
    71  }
    72  
    73  // MarshalYAML implements the marshal interface.
    74  func (v *Logical) MarshalYAML() (interface{}, error) {
    75  	if v.Literal != nil {
    76  		return v.Literal, nil
    77  	}
    78  	return &logical{
    79  		And:     v.And,
    80  		Equal:   v.Equal,
    81  		Matches: v.Matches,
    82  		Not:     v.Not,
    83  		Or:      v.Or,
    84  	}, nil
    85  }
    86  
    87  // IsEmpty returns true if the struct is empty.
    88  func (v *Logical) IsEmpty() bool {
    89  	return v.Not == nil &&
    90  		v.Matches == nil &&
    91  		len(v.And) == 0 &&
    92  		len(v.Equal) == 0 &&
    93  		len(v.Or) == 0
    94  }