/*
 *
 * Copyright 2023 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package serviceconfig

import (
	
	
	
	
	
	
)

// Duration defines JSON marshal and unmarshal methods to conform to the
// protobuf JSON spec defined [here].
//
// [here]: https://protobuf.dev/reference/protobuf/google.protobuf/#duration
type Duration time.Duration

func ( Duration) () string {
	return fmt.Sprint(time.Duration())
}

// MarshalJSON converts from d to a JSON string output.
func ( Duration) () ([]byte, error) {
	 := time.Duration().Nanoseconds()
	 :=  / int64(time.Second)
	 =  % int64(time.Second)

	var  string
	if  < 0 ||  < 0 {
		, ,  = "-", -1*, -1*
	}

	// Generated output always contains 0, 3, 6, or 9 fractional digits,
	// depending on required precision.
	 := fmt.Sprintf("%s%d.%09d", , , )
	 = strings.TrimSuffix(, "000")
	 = strings.TrimSuffix(, "000")
	 = strings.TrimSuffix(, ".000")
	return []byte(fmt.Sprintf("\"%ss\"", )), nil
}

// UnmarshalJSON unmarshals b as a duration JSON string into d.
func ( *Duration) ( []byte) error {
	var  string
	if  := json.Unmarshal(, &);  != nil {
		return 
	}
	if !strings.HasSuffix(, "s") {
		return fmt.Errorf("malformed duration %q: missing seconds unit", )
	}
	 := false
	if [0] == '-' {
		 = true
		 = [1:]
	}
	 := strings.SplitN([:len()-1], ".", 3)
	if len() > 2 {
		return fmt.Errorf("malformed duration %q: too many decimals", )
	}
	// hasDigits is set if either the whole or fractional part of the number is
	// present, since both are optional but one is required.
	 := false
	var ,  int64
	if len([0]) > 0 {
		var  error
		if ,  = strconv.ParseInt([0], 10, 64);  != nil {
			return fmt.Errorf("malformed duration %q: %v", , )
		}
		// Maximum seconds value per the durationpb spec.
		const  = 315_576_000_000
		if  >  {
			return fmt.Errorf("out of range: %q", )
		}
		 = true
	}
	if len() == 2 && len([1]) > 0 {
		if len([1]) > 9 {
			return fmt.Errorf("malformed duration %q: too many digits after decimal", )
		}
		var  error
		if ,  = strconv.ParseInt([1], 10, 64);  != nil {
			return fmt.Errorf("malformed duration %q: %v", , )
		}
		for  := 9;  > len([1]); -- {
			 *= 10
		}
		 = true
	}
	if ! {
		return fmt.Errorf("malformed duration %q: contains no numbers", )
	}

	if  {
		 *= -1
		 *= -1
	}

	// Maximum/minimum seconds/nanoseconds representable by Go's time.Duration.
	const  = math.MaxInt64 / int64(time.Second)
	const  = math.MaxInt64 % int64(time.Second)
	const  = math.MinInt64 / int64(time.Second)
	const  = math.MinInt64 % int64(time.Second)

	if  >  || ( ==  &&  >= ) {
		* = Duration(math.MaxInt64)
	} else if  <  || ( ==  &&  <= ) {
		* = Duration(math.MinInt64)
	} else {
		* = Duration(*int64(time.Second) + )
	}
	return nil
}