gitea源码

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. // Copyright 2024 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. // Package zstd provides a high-level API for reading and writing zstd-compressed data.
  4. // It supports both regular and seekable zstd streams.
  5. // It's not a new wheel, but a wrapper around the zstd and zstd-seekable-format-go packages.
  6. package zstd
  7. import (
  8. "errors"
  9. "io"
  10. seekable "github.com/SaveTheRbtz/zstd-seekable-format-go/pkg"
  11. "github.com/klauspost/compress/zstd"
  12. )
  13. type Writer zstd.Encoder
  14. var _ io.WriteCloser = (*Writer)(nil)
  15. // NewWriter returns a new zstd writer.
  16. func NewWriter(w io.Writer, opts ...WriterOption) (*Writer, error) {
  17. zstdW, err := zstd.NewWriter(w, opts...)
  18. if err != nil {
  19. return nil, err
  20. }
  21. return (*Writer)(zstdW), nil
  22. }
  23. func (w *Writer) Write(p []byte) (int, error) {
  24. return (*zstd.Encoder)(w).Write(p)
  25. }
  26. func (w *Writer) Close() error {
  27. return (*zstd.Encoder)(w).Close()
  28. }
  29. type Reader zstd.Decoder
  30. var _ io.ReadCloser = (*Reader)(nil)
  31. // NewReader returns a new zstd reader.
  32. func NewReader(r io.Reader, opts ...ReaderOption) (*Reader, error) {
  33. zstdR, err := zstd.NewReader(r, opts...)
  34. if err != nil {
  35. return nil, err
  36. }
  37. return (*Reader)(zstdR), nil
  38. }
  39. func (r *Reader) Read(p []byte) (int, error) {
  40. return (*zstd.Decoder)(r).Read(p)
  41. }
  42. func (r *Reader) Close() error {
  43. (*zstd.Decoder)(r).Close() // no error returned
  44. return nil
  45. }
  46. type SeekableWriter struct {
  47. buf []byte
  48. n int
  49. w seekable.Writer
  50. }
  51. var _ io.WriteCloser = (*SeekableWriter)(nil)
  52. // NewSeekableWriter returns a zstd writer to compress data to seekable format.
  53. // blockSize is an important parameter, it should be decided according to the actual business requirements.
  54. // If it's too small, the compression ratio could be very bad, even no compression at all.
  55. // If it's too large, it could cost more traffic when reading the data partially from underlying storage.
  56. func NewSeekableWriter(w io.Writer, blockSize int, opts ...WriterOption) (*SeekableWriter, error) {
  57. zstdW, err := zstd.NewWriter(nil, opts...)
  58. if err != nil {
  59. return nil, err
  60. }
  61. seekableW, err := seekable.NewWriter(w, zstdW)
  62. if err != nil {
  63. return nil, err
  64. }
  65. return &SeekableWriter{
  66. buf: make([]byte, blockSize),
  67. w: seekableW,
  68. }, nil
  69. }
  70. func (w *SeekableWriter) Write(p []byte) (int, error) {
  71. written := 0
  72. for len(p) > 0 {
  73. n := copy(w.buf[w.n:], p)
  74. w.n += n
  75. written += n
  76. p = p[n:]
  77. if w.n == len(w.buf) {
  78. if _, err := w.w.Write(w.buf); err != nil {
  79. return written, err
  80. }
  81. w.n = 0
  82. }
  83. }
  84. return written, nil
  85. }
  86. func (w *SeekableWriter) Close() error {
  87. if w.n > 0 {
  88. if _, err := w.w.Write(w.buf[:w.n]); err != nil {
  89. return err
  90. }
  91. }
  92. return w.w.Close()
  93. }
  94. type SeekableReader struct {
  95. r seekable.Reader
  96. c func() error
  97. }
  98. var _ io.ReadSeekCloser = (*SeekableReader)(nil)
  99. // NewSeekableReader returns a zstd reader to decompress data from seekable format.
  100. func NewSeekableReader(r io.ReadSeeker, opts ...ReaderOption) (*SeekableReader, error) {
  101. zstdR, err := zstd.NewReader(nil, opts...)
  102. if err != nil {
  103. return nil, err
  104. }
  105. seekableR, err := seekable.NewReader(r, zstdR)
  106. if err != nil {
  107. return nil, err
  108. }
  109. ret := &SeekableReader{
  110. r: seekableR,
  111. }
  112. if closer, ok := r.(io.Closer); ok {
  113. ret.c = closer.Close
  114. }
  115. return ret, nil
  116. }
  117. func (r *SeekableReader) Read(p []byte) (int, error) {
  118. return r.r.Read(p)
  119. }
  120. func (r *SeekableReader) Seek(offset int64, whence int) (int64, error) {
  121. return r.r.Seek(offset, whence)
  122. }
  123. func (r *SeekableReader) Close() error {
  124. return errors.Join(
  125. func() error {
  126. if r.c != nil {
  127. return r.c()
  128. }
  129. return nil
  130. }(),
  131. r.r.Close(),
  132. )
  133. }