// Copyright 2019 The Prometheus 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 procfs

import (
	
	
	
	
	

	
)

// Crypto holds info parsed from /proc/crypto.
type Crypto struct {
	Alignmask   *uint64
	Async       bool
	Blocksize   *uint64
	Chunksize   *uint64
	Ctxsize     *uint64
	Digestsize  *uint64
	Driver      string
	Geniv       string
	Internal    string
	Ivsize      *uint64
	Maxauthsize *uint64
	MaxKeysize  *uint64
	MinKeysize  *uint64
	Module      string
	Name        string
	Priority    *int64
	Refcnt      *int64
	Seedsize    *uint64
	Selftest    string
	Type        string
	Walksize    *uint64
}

// Crypto parses an crypto-file (/proc/crypto) and returns a slice of
// structs containing the relevant info.  More information available here:
// https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html
func ( FS) () ([]Crypto, error) {
	 := .proc.Path("crypto")
	,  := util.ReadFileNoStat()
	if  != nil {
		return nil, fmt.Errorf("%w: Cannot read file %v: %w", ErrFileRead, , )

	}

	,  := parseCrypto(bytes.NewReader())
	if  != nil {
		return nil, fmt.Errorf("%w: Cannot parse %v: %w", ErrFileParse, , )
	}

	return , nil
}

// parseCrypto parses a /proc/crypto stream into Crypto elements.
func parseCrypto( io.Reader) ([]Crypto, error) {
	var  []Crypto

	 := bufio.NewScanner()
	for .Scan() {
		 := .Text()
		switch {
		case strings.HasPrefix(, "name"):
			// Each crypto element begins with its name.
			 = append(, Crypto{})
		case  == "":
			continue
		}

		 := strings.Split(, ":")
		if len() != 2 {
			return nil, fmt.Errorf("%w: Cannot parse line: %q", ErrFileParse, )
		}

		 := strings.TrimSpace([0])
		 := strings.TrimSpace([1])

		// Parse the key/value pair into the currently focused element.
		 := &[len()-1]
		if  := .parseKV(, );  != nil {
			return nil, 
		}
	}

	if  := .Err();  != nil {
		return nil, 
	}

	return , nil
}

// parseKV parses a key/value pair into the appropriate field of c.
func ( *Crypto) (,  string) error {
	 := util.NewValueParser()

	switch  {
	case "async":
		// Interpret literal yes as true.
		.Async =  == "yes"
	case "blocksize":
		.Blocksize = .PUInt64()
	case "chunksize":
		.Chunksize = .PUInt64()
	case "digestsize":
		.Digestsize = .PUInt64()
	case "driver":
		.Driver = 
	case "geniv":
		.Geniv = 
	case "internal":
		.Internal = 
	case "ivsize":
		.Ivsize = .PUInt64()
	case "maxauthsize":
		.Maxauthsize = .PUInt64()
	case "max keysize":
		.MaxKeysize = .PUInt64()
	case "min keysize":
		.MinKeysize = .PUInt64()
	case "module":
		.Module = 
	case "name":
		.Name = 
	case "priority":
		.Priority = .PInt64()
	case "refcnt":
		.Refcnt = .PInt64()
	case "seedsize":
		.Seedsize = .PUInt64()
	case "selftest":
		.Selftest = 
	case "type":
		.Type = 
	case "walksize":
		.Walksize = .PUInt64()
	}

	return .Err()
}