1package policy
2
3import (
4	"context"
5	"math/rand"
6
7	"github.com/rclone/rclone/backend/union/upstream"
8	"github.com/rclone/rclone/fs"
9)
10
11func init() {
12	registerPolicy("rand", &Rand{})
13}
14
15// Rand stands for random
16// Calls all and then randomizes. Returns one candidate.
17type Rand struct {
18	All
19}
20
21func (p *Rand) rand(upstreams []*upstream.Fs) *upstream.Fs {
22	return upstreams[rand.Intn(len(upstreams))]
23}
24
25func (p *Rand) randEntries(entries []upstream.Entry) upstream.Entry {
26	return entries[rand.Intn(len(entries))]
27}
28
29// Action category policy, governing the modification of files and directories
30func (p *Rand) Action(ctx context.Context, upstreams []*upstream.Fs, path string) ([]*upstream.Fs, error) {
31	upstreams, err := p.All.Action(ctx, upstreams, path)
32	if err != nil {
33		return nil, err
34	}
35	return []*upstream.Fs{p.rand(upstreams)}, nil
36}
37
38// ActionEntries is ACTION category policy but receiving a set of candidate entries
39func (p *Rand) ActionEntries(entries ...upstream.Entry) ([]upstream.Entry, error) {
40	entries, err := p.All.ActionEntries(entries...)
41	if err != nil {
42		return nil, err
43	}
44	return []upstream.Entry{p.randEntries(entries)}, nil
45}
46
47// Create category policy, governing the creation of files and directories
48func (p *Rand) Create(ctx context.Context, upstreams []*upstream.Fs, path string) ([]*upstream.Fs, error) {
49	upstreams, err := p.All.Create(ctx, upstreams, path)
50	if err != nil {
51		return nil, err
52	}
53	return []*upstream.Fs{p.rand(upstreams)}, nil
54}
55
56// CreateEntries is CREATE category policy but receiving a set of candidate entries
57func (p *Rand) CreateEntries(entries ...upstream.Entry) ([]upstream.Entry, error) {
58	entries, err := p.All.CreateEntries(entries...)
59	if err != nil {
60		return nil, err
61	}
62	return []upstream.Entry{p.randEntries(entries)}, nil
63}
64
65// Search category policy, governing the access to files and directories
66func (p *Rand) Search(ctx context.Context, upstreams []*upstream.Fs, path string) (*upstream.Fs, error) {
67	if len(upstreams) == 0 {
68		return nil, fs.ErrorObjectNotFound
69	}
70	upstreams, err := p.epall(ctx, upstreams, path)
71	if err != nil {
72		return nil, err
73	}
74	return p.rand(upstreams), nil
75}
76
77// SearchEntries is SEARCH category policy but receiving a set of candidate entries
78func (p *Rand) SearchEntries(entries ...upstream.Entry) (upstream.Entry, error) {
79	if len(entries) == 0 {
80		return nil, fs.ErrorObjectNotFound
81	}
82	return p.randEntries(entries), nil
83}
84