github.com/enetx/g@v1.0.80/bytes.go (about)

     1  package g
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"regexp"
     7  	"unicode/utf8"
     8  
     9  	"github.com/enetx/g/cmp"
    10  	"golang.org/x/text/cases"
    11  	"golang.org/x/text/language"
    12  	"golang.org/x/text/unicode/norm"
    13  )
    14  
    15  // NewBytes creates a new Bytes value.
    16  func NewBytes[T ~string | ~[]byte](bs T) Bytes { return Bytes(bs) }
    17  
    18  // Reverse returns a new Bytes with the order of its runes reversed.
    19  func (bs Bytes) Reverse() Bytes {
    20  	reversed := make(Bytes, bs.Len())
    21  	i := 0
    22  
    23  	for bs.Len() > 0 {
    24  		r, size := utf8.DecodeLastRune(bs)
    25  		bs = bs[:bs.Len().Std()-size]
    26  		i += utf8.EncodeRune(reversed[i:], r)
    27  	}
    28  
    29  	return reversed
    30  }
    31  
    32  // Replace replaces the first 'n' occurrences of 'oldB' with 'newB' in the Bytes.
    33  func (bs Bytes) Replace(oldB, newB Bytes, n Int) Bytes { return bytes.Replace(bs, oldB, newB, n.Std()) }
    34  
    35  // ReplaceAll replaces all occurrences of 'oldB' with 'newB' in the Bytes.
    36  func (bs Bytes) ReplaceAll(oldB, newB Bytes) Bytes { return bytes.ReplaceAll(bs, oldB, newB) }
    37  
    38  // ReplaceRegexp replaces all occurrences of the regular expression matches in the Bytes
    39  // with the provided newB and returns the resulting Bytes after the replacement.
    40  func (bs Bytes) ReplaceRegexp(pattern *regexp.Regexp, newB Bytes) Bytes {
    41  	return pattern.ReplaceAll(bs, newB)
    42  }
    43  
    44  // FindRegexp searches the Bytes for the first occurrence of the regular expression pattern
    45  // and returns an Option[Bytes] containing the matched substring.
    46  // If no match is found, the Option[Bytes] will be None.
    47  func (bs Bytes) FindRegexp(pattern *regexp.Regexp) Option[Bytes] {
    48  	result := Bytes(pattern.Find(bs))
    49  	if result.Empty() {
    50  		return None[Bytes]()
    51  	}
    52  
    53  	return Some(result)
    54  }
    55  
    56  // Trim trims the specified characters from the beginning and end of the Bytes.
    57  func (bs Bytes) Trim(cutset String) Bytes { return bytes.Trim(bs, cutset.Std()) }
    58  
    59  // TrimLeft trims the specified characters from the beginning of the Bytes.
    60  func (bs Bytes) TrimLeft(cutset String) Bytes { return bytes.TrimLeft(bs, cutset.Std()) }
    61  
    62  // TrimRight trims the specified characters from the end of the Bytes.
    63  func (bs Bytes) TrimRight(cutset String) Bytes { return bytes.TrimRight(bs, cutset.Std()) }
    64  
    65  // TrimPrefix trims the specified Bytes prefix from the Bytes.
    66  func (bs Bytes) TrimPrefix(cutset Bytes) Bytes { return bytes.TrimPrefix(bs, cutset) }
    67  
    68  // TrimSuffix trims the specified Bytes suffix from the Bytes.
    69  func (bs Bytes) TrimSuffix(cutset Bytes) Bytes { return bytes.TrimSuffix(bs, cutset) }
    70  
    71  // Split splits the Bytes by the specified separator and returns the iterator.
    72  func (bs Bytes) Split(sep ...Bytes) SeqSlice[Bytes] {
    73  	var separator []byte
    74  	if len(sep) != 0 {
    75  		separator = sep[0]
    76  	}
    77  
    78  	return splitBytes(bs, separator, 0)
    79  }
    80  
    81  // SplitAfter splits the Bytes after each instance of the specified separator and returns the iterator.
    82  func (bs Bytes) SplitAfter(sep Bytes) SeqSlice[Bytes] { return splitBytes(bs, sep, sep.Len()) }
    83  
    84  // Fields splits the Bytes into a slice of substrings, removing any whitespace, and returns the iterator.
    85  func (bs Bytes) Fields() SeqSlice[Bytes] { return fieldsBytes(bs) }
    86  
    87  // FieldsBy splits the Bytes into a slice of substrings using a custom function to determine the field boundaries,
    88  // and returns the iterator.
    89  func (bs Bytes) FieldsBy(fn func(r rune) bool) SeqSlice[Bytes] { return fieldsbyBytes(bs, fn) }
    90  
    91  // Add appends the given Bytes to the current Bytes.
    92  func (bs Bytes) Add(obs Bytes) Bytes { return append(bs, obs...) }
    93  
    94  // AddPrefix prepends the given Bytes to the current Bytes.
    95  func (bs Bytes) AddPrefix(obs Bytes) Bytes { return obs.Add(bs) }
    96  
    97  // Std returns the Bytes as a byte slice.
    98  func (bs Bytes) Std() []byte { return bs }
    99  
   100  // Clone creates a new Bytes instance with the same content as the current Bytes.
   101  func (bs Bytes) Clone() Bytes { return bytes.Clone(bs) }
   102  
   103  // Compare compares the Bytes with another Bytes and returns an cmp.Ordering.
   104  func (bs Bytes) Cmp(obs Bytes) cmp.Ordering { return cmp.Ordering(bytes.Compare(bs, obs)) }
   105  
   106  // Contains checks if the Bytes contains the specified Bytes.
   107  func (bs Bytes) Contains(obs Bytes) bool { return bytes.Contains(bs, obs) }
   108  
   109  // ContainsAny checks if the Bytes contains any of the specified Bytes.
   110  func (bs Bytes) ContainsAny(obss ...Bytes) bool {
   111  	for _, obs := range obss {
   112  		if bs.Contains(obs) {
   113  			return true
   114  		}
   115  	}
   116  
   117  	return false
   118  }
   119  
   120  // ContainsAll checks if the Bytes contains all of the specified Bytes.
   121  func (bs Bytes) ContainsAll(obss ...Bytes) bool {
   122  	for _, obs := range obss {
   123  		if !bs.Contains(obs) {
   124  			return false
   125  		}
   126  	}
   127  
   128  	return true
   129  }
   130  
   131  // ContainsAnyChars checks if the given Bytes contains any characters from the input String.
   132  func (bs Bytes) ContainsAnyChars(chars String) bool { return bytes.ContainsAny(bs, chars.Std()) }
   133  
   134  // ContainsRune checks if the Bytes contains the specified rune.
   135  func (bs Bytes) ContainsRune(r rune) bool { return bytes.ContainsRune(bs, r) }
   136  
   137  // Count counts the number of occurrences of the specified Bytes in the Bytes.
   138  func (bs Bytes) Count(obs Bytes) Int { return Int(bytes.Count(bs, obs)) }
   139  
   140  // Empty checks if the Bytes is empty.
   141  func (bs Bytes) Empty() bool { return bs == nil || len(bs) == 0 }
   142  
   143  // Eq checks if the Bytes is equal to another Bytes.
   144  func (bs Bytes) Eq(obs Bytes) bool { return bs.Cmp(obs).IsEq() }
   145  
   146  // EqFold compares two Bytes slices case-insensitively.
   147  func (bs Bytes) EqFold(obs Bytes) bool { return bytes.EqualFold(bs, obs) }
   148  
   149  // Gt checks if the Bytes is greater than another Bytes.
   150  func (bs Bytes) Gt(obs Bytes) bool { return bs.Cmp(obs).IsGt() }
   151  
   152  // ToString returns the Bytes as an String.
   153  func (bs Bytes) ToString() String { return String(bs) }
   154  
   155  // Index returns the index of the first instance of obs in bs, or -1 if bs is not present in obs.
   156  func (bs Bytes) Index(obs Bytes) Int { return Int(bytes.Index(bs, obs)) }
   157  
   158  // IndexRegexp searches for the first occurrence of the regular expression pattern in the Bytes.
   159  // If a match is found, it returns an Option containing an Slice with the start and end indices of the match.
   160  // If no match is found, it returns None.
   161  func (bs Bytes) IndexRegexp(pattern *regexp.Regexp) Option[Slice[Int]] {
   162  	result := SliceMap(pattern.FindIndex(bs), NewInt)
   163  	if result.Empty() {
   164  		return None[Slice[Int]]()
   165  	}
   166  
   167  	return Some(result)
   168  }
   169  
   170  // FindAllRegexp searches the Bytes for all occurrences of the regular expression pattern
   171  // and returns an Option[Slice[Bytes]] containing a slice of matched substrings.
   172  // If no matches are found, the Option[Slice[Bytes]] will be None.
   173  func (bs Bytes) FindAllRegexp(pattern *regexp.Regexp) Option[Slice[Bytes]] {
   174  	return bs.FindAllRegexpN(pattern, -1)
   175  }
   176  
   177  // FindAllRegexpN searches the Bytes for up to n occurrences of the regular expression pattern
   178  // and returns an Option[Slice[Bytes]] containing a slice of matched substrings.
   179  // If no matches are found, the Option[Slice[Bytes]] will be None.
   180  // If n is negative, all occurrences will be returned.
   181  func (bs Bytes) FindAllRegexpN(pattern *regexp.Regexp, n Int) Option[Slice[Bytes]] {
   182  	result := SliceMap(pattern.FindAll(bs, n.Std()), NewBytes)
   183  	if result.Empty() {
   184  		return None[Slice[Bytes]]()
   185  	}
   186  
   187  	return Some(result)
   188  }
   189  
   190  // FindSubmatchRegexp searches the Bytes for the first occurrence of the regular expression pattern
   191  // and returns an Option[Slice[Bytes]] containing the matched substrings and submatches.
   192  // The Option[Slice[Bytes]] will contain an Slice[Bytes] for each match,
   193  // where each Slice[Bytes] will contain the full match at index 0, followed by any captured submatches.
   194  // If no match is found, the Option[Slice[Bytes]] will be None.
   195  func (bs Bytes) FindSubmatchRegexp(pattern *regexp.Regexp) Option[Slice[Bytes]] {
   196  	result := SliceMap(pattern.FindSubmatch(bs), NewBytes)
   197  	if result.Empty() {
   198  		return None[Slice[Bytes]]()
   199  	}
   200  
   201  	return Some(result)
   202  }
   203  
   204  // FindAllSubmatchRegexp searches the Bytes for all occurrences of the regular expression pattern
   205  // and returns an Option[Slice[Slice[Bytes]]] containing the matched substrings and submatches.
   206  // The Option[Slice[Slice[Bytes]]] will contain an Slice[Bytes] for each match,
   207  // where each Slice[Bytes] will contain the full match at index 0, followed by any captured submatches.
   208  // If no match is found, the Option[Slice[Slice[Bytes]]] will be None.
   209  // This method is equivalent to calling SubmatchAllRegexpN with n = -1, which means it finds all occurrences.
   210  func (bs Bytes) FindAllSubmatchRegexp(pattern *regexp.Regexp) Option[Slice[Slice[Bytes]]] {
   211  	return bs.FindAllSubmatchRegexpN(pattern, -1)
   212  }
   213  
   214  // FindAllSubmatchRegexpN searches the Bytes for occurrences of the regular expression pattern
   215  // and returns an Option[Slice[Slice[Bytes]]] containing the matched substrings and submatches.
   216  // The Option[Slice[Slice[Bytes]]] will contain an Slice[Bytes] for each match,
   217  // where each Slice[Bytes] will contain the full match at index 0, followed by any captured submatches.
   218  // If no match is found, the Option[Slice[Slice[Bytes]]] will be None.
   219  // The 'n' parameter specifies the maximum number of matches to find. If n is negative, it finds all occurrences.
   220  func (bs Bytes) FindAllSubmatchRegexpN(pattern *regexp.Regexp, n Int) Option[Slice[Slice[Bytes]]] {
   221  	var result Slice[Slice[Bytes]]
   222  
   223  	for _, v := range pattern.FindAllSubmatch(bs, n.Std()) {
   224  		result = append(result, SliceMap(v, NewBytes))
   225  	}
   226  
   227  	if result.Empty() {
   228  		return None[Slice[Slice[Bytes]]]()
   229  	}
   230  
   231  	return Some(result)
   232  }
   233  
   234  // LastIndex returns the index of the last instance of obs in bs, or -1 if obs is not present in bs.
   235  func (bs Bytes) LastIndex(obs Bytes) Int { return Int(bytes.LastIndex(bs, obs)) }
   236  
   237  // IndexByte returns the index of the first instance of the byte b in bs, or -1 if b is not
   238  // present in bs.
   239  func (bs Bytes) IndexByte(b byte) Int { return Int(bytes.IndexByte(bs, b)) }
   240  
   241  // LastIndexByte returns the index of the last instance of the byte b in bs, or -1 if b is not
   242  // present in bs.
   243  func (bs Bytes) LastIndexByte(b byte) Int { return Int(bytes.LastIndexByte(bs, b)) }
   244  
   245  // IndexRune returns the index of the first instance of the rune r in bs, or -1 if r is not
   246  // present in bs.
   247  func (bs Bytes) IndexRune(r rune) Int { return Int(bytes.IndexRune(bs, r)) }
   248  
   249  // Len returns the length of the Bytes.
   250  func (bs Bytes) Len() Int { return Int(len(bs)) }
   251  
   252  // LenRunes returns the number of runes in the Bytes.
   253  func (bs Bytes) LenRunes() Int { return Int(utf8.RuneCount(bs)) }
   254  
   255  // Lt checks if the Bytes is less than another Bytes.
   256  func (bs Bytes) Lt(obs Bytes) bool { return bs.Cmp(obs).IsLt() }
   257  
   258  // Map applies a function to each rune in the Bytes and returns the modified Bytes.
   259  func (bs Bytes) Map(fn func(rune) rune) Bytes { return bytes.Map(fn, bs) }
   260  
   261  // NormalizeNFC returns a new Bytes with its Unicode characters normalized using the NFC form.
   262  func (bs Bytes) NormalizeNFC() Bytes { return norm.NFC.Bytes(bs) }
   263  
   264  // Ne checks if the Bytes is not equal to another Bytes.
   265  func (bs Bytes) Ne(obs Bytes) bool { return !bs.Eq(obs) }
   266  
   267  // NotEmpty checks if the Bytes is not empty.
   268  func (bs Bytes) NotEmpty() bool { return !bs.Empty() }
   269  
   270  // Reader returns a *bytes.Reader initialized with the content of Bytes.
   271  func (bs Bytes) Reader() *bytes.Reader { return bytes.NewReader(bs) }
   272  
   273  // Repeat returns a new Bytes consisting of the current Bytes repeated 'count' times.
   274  func (bs Bytes) Repeat(count Int) Bytes { return bytes.Repeat(bs, count.Std()) }
   275  
   276  // ToRunes returns the Bytes as a slice of runes.
   277  func (bs Bytes) ToRunes() []rune { return bytes.Runes(bs) }
   278  
   279  // Title converts the Bytes to title case.
   280  func (bs Bytes) Title() Bytes { return cases.Title(language.English).Bytes(bs) }
   281  
   282  // Lower converts the Bytes to lowercase.
   283  func (bs Bytes) Lower() Bytes { return cases.Lower(language.English).Bytes(bs) }
   284  
   285  // Upper converts the Bytes to uppercase.
   286  func (bs Bytes) Upper() Bytes { return cases.Upper(language.English).Bytes(bs) }
   287  
   288  // TrimSpace trims white space characters from the beginning and end of the Bytes.
   289  func (bs Bytes) TrimSpace() Bytes { return bytes.TrimSpace(bs) }
   290  
   291  // Print prints the content of the Bytes to the standard output (console)
   292  // and returns the Bytes unchanged.
   293  func (bs Bytes) Print() Bytes { fmt.Println(bs); return bs }