UniRx 에셋 추가

This commit is contained in:
Mingu Kim
2025-06-02 00:27:36 +09:00
parent 915f292d7d
commit 8a54d47b56
510 changed files with 42973 additions and 0 deletions

View File

@@ -0,0 +1,207 @@
using System;
using UniRx.Operators;
namespace UniRx.Operators
{
internal class AggregateObservable<TSource> : OperatorObservableBase<TSource>
{
readonly IObservable<TSource> source;
readonly Func<TSource, TSource, TSource> accumulator;
public AggregateObservable(IObservable<TSource> source, Func<TSource, TSource, TSource> accumulator)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.accumulator = accumulator;
}
protected override IDisposable SubscribeCore(IObserver<TSource> observer, IDisposable cancel)
{
return source.Subscribe(new Aggregate(this, observer, cancel));
}
class Aggregate : OperatorObserverBase<TSource, TSource>
{
readonly AggregateObservable<TSource> parent;
TSource accumulation;
bool seenValue;
public Aggregate(AggregateObservable<TSource> parent, IObserver<TSource> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
this.seenValue = false;
}
public override void OnNext(TSource value)
{
if (!seenValue)
{
seenValue = true;
accumulation = value;
}
else
{
try
{
accumulation = parent.accumulator(accumulation, value);
}
catch (Exception ex)
{
try { observer.OnError(ex); }
finally { Dispose(); }
return;
}
}
}
public override void OnError(Exception error)
{
try { observer.OnError(error); }
finally { Dispose(); }
}
public override void OnCompleted()
{
if (!seenValue)
{
throw new InvalidOperationException("Sequence contains no elements.");
}
observer.OnNext(accumulation);
try { observer.OnCompleted(); }
finally { Dispose(); }
}
}
}
internal class AggregateObservable<TSource, TAccumulate> : OperatorObservableBase<TAccumulate>
{
readonly IObservable<TSource> source;
readonly TAccumulate seed;
readonly Func<TAccumulate, TSource, TAccumulate> accumulator;
public AggregateObservable(IObservable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.seed = seed;
this.accumulator = accumulator;
}
protected override IDisposable SubscribeCore(IObserver<TAccumulate> observer, IDisposable cancel)
{
return source.Subscribe(new Aggregate(this, observer, cancel));
}
class Aggregate : OperatorObserverBase<TSource, TAccumulate>
{
readonly AggregateObservable<TSource, TAccumulate> parent;
TAccumulate accumulation;
public Aggregate(AggregateObservable<TSource, TAccumulate> parent, IObserver<TAccumulate> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
this.accumulation = parent.seed;
}
public override void OnNext(TSource value)
{
try
{
accumulation = parent.accumulator(accumulation, value);
}
catch (Exception ex)
{
try { observer.OnError(ex); }
finally { Dispose(); }
return;
}
}
public override void OnError(Exception error)
{
try { observer.OnError(error); }
finally { Dispose(); }
}
public override void OnCompleted()
{
observer.OnNext(accumulation);
try { observer.OnCompleted(); }
finally { Dispose(); }
}
}
}
internal class AggregateObservable<TSource, TAccumulate, TResult> : OperatorObservableBase<TResult>
{
readonly IObservable<TSource> source;
readonly TAccumulate seed;
readonly Func<TAccumulate, TSource, TAccumulate> accumulator;
readonly Func<TAccumulate, TResult> resultSelector;
public AggregateObservable(IObservable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator, Func<TAccumulate, TResult> resultSelector)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.seed = seed;
this.accumulator = accumulator;
this.resultSelector = resultSelector;
}
protected override IDisposable SubscribeCore(IObserver<TResult> observer, IDisposable cancel)
{
return source.Subscribe(new Aggregate(this, observer, cancel));
}
class Aggregate : OperatorObserverBase<TSource, TResult>
{
readonly AggregateObservable<TSource, TAccumulate, TResult> parent;
TAccumulate accumulation;
public Aggregate(AggregateObservable<TSource, TAccumulate, TResult> parent, IObserver<TResult> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
this.accumulation = parent.seed;
}
public override void OnNext(TSource value)
{
try
{
accumulation = parent.accumulator(accumulation, value);
}
catch (Exception ex)
{
try { observer.OnError(ex); }
finally { Dispose(); }
return;
}
}
public override void OnError(Exception error)
{
try { observer.OnError(error); }
finally { Dispose(); }
}
public override void OnCompleted()
{
TResult result;
try
{
result = parent.resultSelector(accumulation);
}
catch (Exception ex)
{
OnError(ex);
return;
}
observer.OnNext(result);
try { observer.OnCompleted(); }
finally { Dispose(); }
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: f777fc54ecf275349a3f007e760705b3
timeCreated: 1455373902
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,182 @@
using System;
using System.Collections.Generic;
namespace UniRx.Operators
{
internal class AmbObservable<T> : OperatorObservableBase<T>
{
readonly IObservable<T> source;
readonly IObservable<T> second;
public AmbObservable(IObservable<T> source, IObservable<T> second)
: base(source.IsRequiredSubscribeOnCurrentThread() || second.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.second = second;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
return new AmbOuterObserver(this, observer, cancel).Run();
}
class AmbOuterObserver : OperatorObserverBase<T, T>
{
enum AmbState
{
Left, Right, Neither
}
readonly AmbObservable<T> parent;
readonly object gate = new object();
SingleAssignmentDisposable leftSubscription;
SingleAssignmentDisposable rightSubscription;
AmbState choice = AmbState.Neither;
public AmbOuterObserver(AmbObservable<T> parent, IObserver<T> observer, IDisposable cancel)
: base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
leftSubscription = new SingleAssignmentDisposable();
rightSubscription = new SingleAssignmentDisposable();
var d = StableCompositeDisposable.Create(leftSubscription, rightSubscription);
var left = new Amb();
left.targetDisposable = d;
left.targetObserver = new AmbDecisionObserver(this, AmbState.Left, rightSubscription, left);
var right = new Amb();
right.targetDisposable = d;
right.targetObserver = new AmbDecisionObserver(this, AmbState.Right, leftSubscription, right);
leftSubscription.Disposable = parent.source.Subscribe(left);
rightSubscription.Disposable = parent.second.Subscribe(right);
return d;
}
public override void OnNext(T value)
{
// no use
}
public override void OnError(Exception error)
{
// no use
}
public override void OnCompleted()
{
// no use
}
class Amb : IObserver<T>
{
public IObserver<T> targetObserver;
public IDisposable targetDisposable;
public void OnNext(T value)
{
targetObserver.OnNext(value);
}
public void OnError(Exception error)
{
try
{
targetObserver.OnError(error);
}
finally
{
targetObserver = UniRx.InternalUtil.EmptyObserver<T>.Instance;
targetDisposable.Dispose();
}
}
public void OnCompleted()
{
try
{
targetObserver.OnCompleted();
}
finally
{
targetObserver = UniRx.InternalUtil.EmptyObserver<T>.Instance;
targetDisposable.Dispose();
}
}
}
class AmbDecisionObserver : IObserver<T>
{
readonly AmbOuterObserver parent;
readonly AmbState me;
readonly IDisposable otherSubscription;
readonly Amb self;
public AmbDecisionObserver(AmbOuterObserver parent, AmbState me, IDisposable otherSubscription, Amb self)
{
this.parent = parent;
this.me = me;
this.otherSubscription = otherSubscription;
this.self = self;
}
public void OnNext(T value)
{
lock (parent.gate)
{
if (parent.choice == AmbState.Neither)
{
parent.choice = me;
otherSubscription.Dispose();
self.targetObserver = parent.observer;
}
if (parent.choice == me) self.targetObserver.OnNext(value);
}
}
public void OnError(Exception error)
{
lock (parent.gate)
{
if (parent.choice == AmbState.Neither)
{
parent.choice = me;
otherSubscription.Dispose();
self.targetObserver = parent.observer;
}
if (parent.choice == me)
{
self.targetObserver.OnError(error);
}
}
}
public void OnCompleted()
{
lock (parent.gate)
{
if (parent.choice == AmbState.Neither)
{
parent.choice = me;
otherSubscription.Dispose();
self.targetObserver = parent.observer;
}
if (parent.choice == me)
{
self.targetObserver.OnCompleted();
}
}
}
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: ad1a22922a735ee479baf0e179648532
timeCreated: 1455373900
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,45 @@
using System;
using UniRx.Operators;
namespace UniRx.Operators
{
internal class AsObservableObservable<T> : OperatorObservableBase<T>
{
readonly IObservable<T> source;
public AsObservableObservable(IObservable<T> source)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
return source.Subscribe(new AsObservable(observer, cancel));
}
class AsObservable : OperatorObserverBase<T, T>
{
public AsObservable(IObserver<T> observer, IDisposable cancel) : base(observer, cancel)
{
}
public override void OnNext(T value)
{
base.observer.OnNext(value);
}
public override void OnError(Exception error)
{
try { observer.OnError(error); }
finally { Dispose(); }
}
public override void OnCompleted()
{
try { observer.OnCompleted(); }
finally { Dispose(); }
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 9e4851fd48b2b42469d71b311254877b
timeCreated: 1455373900
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,46 @@
using System;
using UniRx.Operators;
namespace UniRx.Operators
{
internal class AsSingleUnitObservableObservable<T> : OperatorObservableBase<Unit>
{
readonly IObservable<T> source;
public AsSingleUnitObservableObservable(IObservable<T> source)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
}
protected override IDisposable SubscribeCore(IObserver<Unit> observer, IDisposable cancel)
{
return source.Subscribe(new AsSingleUnitObservable(observer, cancel));
}
class AsSingleUnitObservable : OperatorObserverBase<T, Unit>
{
public AsSingleUnitObservable(IObserver<Unit> observer, IDisposable cancel) : base(observer, cancel)
{
}
public override void OnNext(T value)
{
}
public override void OnError(Exception error)
{
try { observer.OnError(error); }
finally { Dispose(); }
}
public override void OnCompleted()
{
observer.OnNext(Unit.Default);
try { observer.OnCompleted(); }
finally { Dispose(); }
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 3b5e05dba2d3aca4e9c3a6312bef8690
timeCreated: 1462636004
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,45 @@
using System;
namespace UniRx.Operators
{
internal class AsUnitObservableObservable<T> : OperatorObservableBase<Unit>
{
readonly IObservable<T> source;
public AsUnitObservableObservable(IObservable<T> source)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
}
protected override IDisposable SubscribeCore(IObserver<Unit> observer, IDisposable cancel)
{
return source.Subscribe(new AsUnitObservable(observer, cancel));
}
class AsUnitObservable : OperatorObserverBase<T, Unit>
{
public AsUnitObservable(IObserver<Unit> observer, IDisposable cancel)
: base(observer, cancel)
{
}
public override void OnNext(T value)
{
base.observer.OnNext(Unit.Default);
}
public override void OnError(Exception error)
{
try { observer.OnError(error); }
finally { Dispose(); }
}
public override void OnCompleted()
{
try { observer.OnCompleted(); }
finally { Dispose(); }
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 236f5f407bf92c949844fcaf450af450
timeCreated: 1455373897
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,624 @@
using System;
using System.Collections.Generic;
using UniRx.Operators;
namespace UniRx.Operators
{
internal class BufferObservable<T> : OperatorObservableBase<IList<T>>
{
readonly IObservable<T> source;
readonly int count;
readonly int skip;
readonly TimeSpan timeSpan;
readonly TimeSpan timeShift;
readonly IScheduler scheduler;
public BufferObservable(IObservable<T> source, int count, int skip)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.count = count;
this.skip = skip;
}
public BufferObservable(IObservable<T> source, TimeSpan timeSpan, TimeSpan timeShift, IScheduler scheduler)
: base(scheduler == Scheduler.CurrentThread || source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.timeSpan = timeSpan;
this.timeShift = timeShift;
this.scheduler = scheduler;
}
public BufferObservable(IObservable<T> source, TimeSpan timeSpan, int count, IScheduler scheduler)
: base(scheduler == Scheduler.CurrentThread || source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.timeSpan = timeSpan;
this.count = count;
this.scheduler = scheduler;
}
protected override IDisposable SubscribeCore(IObserver<IList<T>> observer, IDisposable cancel)
{
// count,skip
if (scheduler == null)
{
if (skip == 0)
{
return new Buffer(this, observer, cancel).Run();
}
else
{
return new Buffer_(this, observer, cancel).Run();
}
}
else
{
// time + count
if (count > 0)
{
return new BufferTC(this, observer, cancel).Run();
}
else
{
if (timeSpan == timeShift)
{
return new BufferT(this, observer, cancel).Run();
}
else
{
return new BufferTS(this, observer, cancel).Run();
}
}
}
}
// count only
class Buffer : OperatorObserverBase<T, IList<T>>
{
readonly BufferObservable<T> parent;
List<T> list;
public Buffer(BufferObservable<T> parent, IObserver<IList<T>> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
list = new List<T>(parent.count);
return parent.source.Subscribe(this);
}
public override void OnNext(T value)
{
list.Add(value);
if (list.Count == parent.count)
{
observer.OnNext(list);
list = new List<T>(parent.count);
}
}
public override void OnError(Exception error)
{
try { observer.OnError(error); } finally { Dispose(); }
}
public override void OnCompleted()
{
if (list.Count > 0)
{
observer.OnNext(list);
}
try { observer.OnCompleted(); } finally { Dispose(); }
}
}
// count and skip
class Buffer_ : OperatorObserverBase<T, IList<T>>
{
readonly BufferObservable<T> parent;
Queue<List<T>> q;
int index;
public Buffer_(BufferObservable<T> parent, IObserver<IList<T>> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
q = new Queue<List<T>>();
index = -1;
return parent.source.Subscribe(this);
}
public override void OnNext(T value)
{
index++;
if (index % parent.skip == 0)
{
q.Enqueue(new List<T>(parent.count));
}
var len = q.Count;
for (int i = 0; i < len; i++)
{
var list = q.Dequeue();
list.Add(value);
if (list.Count == parent.count)
{
observer.OnNext(list);
}
else
{
q.Enqueue(list);
}
}
}
public override void OnError(Exception error)
{
try { observer.OnError(error); } finally { Dispose(); }
}
public override void OnCompleted()
{
foreach (var list in q)
{
observer.OnNext(list);
}
try { observer.OnCompleted(); } finally { Dispose(); }
}
}
// timespan = timeshift
class BufferT : OperatorObserverBase<T, IList<T>>
{
static readonly T[] EmptyArray = new T[0];
readonly BufferObservable<T> parent;
readonly object gate = new object();
List<T> list;
public BufferT(BufferObservable<T> parent, IObserver<IList<T>> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
list = new List<T>();
var timerSubscription = Observable.Interval(parent.timeSpan, parent.scheduler)
.Subscribe(new Buffer(this));
var sourceSubscription = parent.source.Subscribe(this);
return StableCompositeDisposable.Create(timerSubscription, sourceSubscription);
}
public override void OnNext(T value)
{
lock (gate)
{
list.Add(value);
}
}
public override void OnError(Exception error)
{
try { observer.OnError(error); } finally { Dispose(); }
}
public override void OnCompleted()
{
List<T> currentList;
lock (gate)
{
currentList = list;
}
observer.OnNext(currentList);
try { observer.OnCompleted(); } finally { Dispose(); }
}
class Buffer : IObserver<long>
{
BufferT parent;
public Buffer(BufferT parent)
{
this.parent = parent;
}
public void OnNext(long value)
{
var isZero = false;
List<T> currentList;
lock (parent.gate)
{
currentList = parent.list;
if (currentList.Count != 0)
{
parent.list = new List<T>();
}
else
{
isZero = true;
}
}
parent.observer.OnNext((isZero) ? (IList<T>)EmptyArray : currentList);
}
public void OnError(Exception error)
{
}
public void OnCompleted()
{
}
}
}
// timespan + timeshift
class BufferTS : OperatorObserverBase<T, IList<T>>
{
readonly BufferObservable<T> parent;
readonly object gate = new object();
Queue<IList<T>> q;
TimeSpan totalTime;
TimeSpan nextShift;
TimeSpan nextSpan;
SerialDisposable timerD;
public BufferTS(BufferObservable<T> parent, IObserver<IList<T>> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
totalTime = TimeSpan.Zero;
nextShift = parent.timeShift;
nextSpan = parent.timeSpan;
q = new Queue<IList<T>>();
timerD = new SerialDisposable();
q.Enqueue(new List<T>());
CreateTimer();
var subscription = parent.source.Subscribe(this);
return StableCompositeDisposable.Create(subscription, timerD);
}
void CreateTimer()
{
var m = new SingleAssignmentDisposable();
timerD.Disposable = m;
var isSpan = false;
var isShift = false;
if (nextSpan == nextShift)
{
isSpan = true;
isShift = true;
}
else if (nextSpan < nextShift)
isSpan = true;
else
isShift = true;
var newTotalTime = isSpan ? nextSpan : nextShift;
var ts = newTotalTime - totalTime;
totalTime = newTotalTime;
if (isSpan)
nextSpan += parent.timeShift;
if (isShift)
nextShift += parent.timeShift;
m.Disposable = parent.scheduler.Schedule(ts, () =>
{
lock (gate)
{
if (isShift)
{
var s = new List<T>();
q.Enqueue(s);
}
if (isSpan)
{
var s = q.Dequeue();
observer.OnNext(s);
}
}
CreateTimer();
});
}
public override void OnNext(T value)
{
lock (gate)
{
foreach (var s in q)
{
s.Add(value);
}
}
}
public override void OnError(Exception error)
{
try { observer.OnError(error); } finally { Dispose(); }
}
public override void OnCompleted()
{
lock (gate)
{
foreach (var list in q)
{
observer.OnNext(list);
}
try { observer.OnCompleted(); } finally { Dispose(); }
}
}
}
// timespan + count
class BufferTC : OperatorObserverBase<T, IList<T>>
{
static readonly T[] EmptyArray = new T[0]; // cache
readonly BufferObservable<T> parent;
readonly object gate = new object();
List<T> list;
long timerId;
SerialDisposable timerD;
public BufferTC(BufferObservable<T> parent, IObserver<IList<T>> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
list = new List<T>();
timerId = 0L;
timerD = new SerialDisposable();
CreateTimer();
var subscription = parent.source.Subscribe(this);
return StableCompositeDisposable.Create(subscription, timerD);
}
void CreateTimer()
{
var currentTimerId = timerId;
var timerS = new SingleAssignmentDisposable();
timerD.Disposable = timerS; // restart timer(dispose before)
var periodicScheduler = parent.scheduler as ISchedulerPeriodic;
if (periodicScheduler != null)
{
timerS.Disposable = periodicScheduler.SchedulePeriodic(parent.timeSpan, () => OnNextTick(currentTimerId));
}
else
{
timerS.Disposable = parent.scheduler.Schedule(parent.timeSpan, self => OnNextRecursive(currentTimerId, self));
}
}
void OnNextTick(long currentTimerId)
{
var isZero = false;
List<T> currentList;
lock (gate)
{
if (currentTimerId != timerId) return;
currentList = list;
if (currentList.Count != 0)
{
list = new List<T>();
}
else
{
isZero = true;
}
}
observer.OnNext((isZero) ? (IList<T>)EmptyArray : currentList);
}
void OnNextRecursive(long currentTimerId, Action<TimeSpan> self)
{
var isZero = false;
List<T> currentList;
lock (gate)
{
if (currentTimerId != timerId) return;
currentList = list;
if (currentList.Count != 0)
{
list = new List<T>();
}
else
{
isZero = true;
}
}
observer.OnNext((isZero) ? (IList<T>)EmptyArray : currentList);
self(parent.timeSpan);
}
public override void OnNext(T value)
{
List<T> currentList = null;
lock (gate)
{
list.Add(value);
if (list.Count == parent.count)
{
currentList = list;
list = new List<T>();
timerId++;
CreateTimer();
}
}
if (currentList != null)
{
observer.OnNext(currentList);
}
}
public override void OnError(Exception error)
{
try { observer.OnError(error); } finally { Dispose(); }
}
public override void OnCompleted()
{
List<T> currentList;
lock (gate)
{
timerId++;
currentList = list;
}
observer.OnNext(currentList);
try { observer.OnCompleted(); } finally { Dispose(); }
}
}
}
internal class BufferObservable<TSource, TWindowBoundary> : OperatorObservableBase<IList<TSource>>
{
readonly IObservable<TSource> source;
readonly IObservable<TWindowBoundary> windowBoundaries;
public BufferObservable(IObservable<TSource> source, IObservable<TWindowBoundary> windowBoundaries)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.windowBoundaries = windowBoundaries;
}
protected override IDisposable SubscribeCore(IObserver<IList<TSource>> observer, IDisposable cancel)
{
return new Buffer(this, observer, cancel).Run();
}
class Buffer : OperatorObserverBase<TSource, IList<TSource>>
{
static readonly TSource[] EmptyArray = new TSource[0]; // cache
readonly BufferObservable<TSource, TWindowBoundary> parent;
object gate = new object();
List<TSource> list;
public Buffer(BufferObservable<TSource, TWindowBoundary> parent, IObserver<IList<TSource>> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
list = new List<TSource>();
var sourceSubscription = parent.source.Subscribe(this);
var windowSubscription = parent.windowBoundaries.Subscribe(new Buffer_(this));
return StableCompositeDisposable.Create(sourceSubscription, windowSubscription);
}
public override void OnNext(TSource value)
{
lock (gate)
{
list.Add(value);
}
}
public override void OnError(Exception error)
{
lock (gate)
{
try { observer.OnError(error); } finally { Dispose(); }
}
}
public override void OnCompleted()
{
lock (gate)
{
var currentList = list;
list = new List<TSource>(); // safe
observer.OnNext(currentList);
try { observer.OnCompleted(); } finally { Dispose(); }
}
}
class Buffer_ : IObserver<TWindowBoundary>
{
readonly Buffer parent;
public Buffer_(Buffer parent)
{
this.parent = parent;
}
public void OnNext(TWindowBoundary value)
{
var isZero = false;
List<TSource> currentList;
lock (parent.gate)
{
currentList = parent.list;
if (currentList.Count != 0)
{
parent.list = new List<TSource>();
}
else
{
isZero = true;
}
}
if (isZero)
{
parent.observer.OnNext(EmptyArray);
}
else
{
parent.observer.OnNext(currentList);
}
}
public void OnError(Exception error)
{
parent.OnError(error);
}
public void OnCompleted()
{
parent.OnCompleted();
}
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 4137aec9640d3ea41a740d677026aa8c
timeCreated: 1455373898
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,57 @@
using System;
namespace UniRx.Operators
{
internal class CastObservable<TSource, TResult> : OperatorObservableBase<TResult>
{
readonly IObservable<TSource> source;
public CastObservable(IObservable<TSource> source)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
}
protected override IDisposable SubscribeCore(IObserver<TResult> observer, IDisposable cancel)
{
return source.Subscribe(new Cast(observer, cancel));
}
class Cast : OperatorObserverBase<TSource, TResult>
{
public Cast(IObserver<TResult> observer, IDisposable cancel)
: base(observer, cancel)
{
}
public override void OnNext(TSource value)
{
var castValue = default(TResult);
try
{
castValue = (TResult)(object)value;
}
catch (Exception ex)
{
try { observer.OnError(ex); }
finally { Dispose(); }
return;
}
observer.OnNext(castValue);
}
public override void OnError(Exception error)
{
try { observer.OnError(error); }
finally { Dispose(); }
}
public override void OnCompleted()
{
try { observer.OnCompleted(); }
finally { Dispose(); }
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: e70ae559c9b927742acbff91d50b3b22
timeCreated: 1455373901
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,217 @@
using System;
using System.Collections.Generic;
namespace UniRx.Operators
{
internal class CatchObservable<T, TException> : OperatorObservableBase<T>
where TException : Exception
{
readonly IObservable<T> source;
readonly Func<TException, IObservable<T>> errorHandler;
public CatchObservable(IObservable<T> source, Func<TException, IObservable<T>> errorHandler)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.errorHandler = errorHandler;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
return new Catch(this, observer, cancel).Run();
}
class Catch : OperatorObserverBase<T, T>
{
readonly CatchObservable<T, TException> parent;
SingleAssignmentDisposable sourceSubscription;
SingleAssignmentDisposable exceptionSubscription;
public Catch(CatchObservable<T, TException> parent, IObserver<T> observer, IDisposable cancel)
: base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
this.sourceSubscription = new SingleAssignmentDisposable();
this.exceptionSubscription = new SingleAssignmentDisposable();
this.sourceSubscription.Disposable = parent.source.Subscribe(this);
return StableCompositeDisposable.Create(sourceSubscription, exceptionSubscription);
}
public override void OnNext(T value)
{
base.observer.OnNext(value);
}
public override void OnError(Exception error)
{
var e = error as TException;
if (e != null)
{
IObservable<T> next;
try
{
if (parent.errorHandler == Stubs.CatchIgnore<T>)
{
next = Observable.Empty<T>(); // for avoid iOS AOT
}
else
{
next = parent.errorHandler(e);
}
}
catch (Exception ex)
{
try { observer.OnError(ex); } finally { Dispose(); };
return;
}
exceptionSubscription.Disposable = next.Subscribe(observer);
}
else
{
try { observer.OnError(error); } finally { Dispose(); };
return;
}
}
public override void OnCompleted()
{
try { observer.OnCompleted(); } finally { Dispose(); };
}
}
}
internal class CatchObservable<T> : OperatorObservableBase<T>
{
readonly IEnumerable<IObservable<T>> sources;
public CatchObservable(IEnumerable<IObservable<T>> sources)
: base(true)
{
this.sources = sources;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
return new Catch(this, observer, cancel).Run();
}
class Catch : OperatorObserverBase<T, T>
{
readonly CatchObservable<T> parent;
readonly object gate = new object();
bool isDisposed;
IEnumerator<IObservable<T>> e;
SerialDisposable subscription;
Exception lastException;
Action nextSelf;
public Catch(CatchObservable<T> parent, IObserver<T> observer, IDisposable cancel)
: base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
isDisposed = false;
e = parent.sources.GetEnumerator();
subscription = new SerialDisposable();
var schedule = Scheduler.DefaultSchedulers.TailRecursion.Schedule(RecursiveRun);
return StableCompositeDisposable.Create(schedule, subscription, Disposable.Create(() =>
{
lock (gate)
{
this.isDisposed = true;
this.e.Dispose();
}
}));
}
void RecursiveRun(Action self)
{
lock (gate)
{
nextSelf = self;
if (isDisposed) return;
var current = default(IObservable<T>);
var hasNext = false;
var ex = default(Exception);
try
{
hasNext = e.MoveNext();
if (hasNext)
{
current = e.Current;
if (current == null) throw new InvalidOperationException("sequence is null.");
}
else
{
e.Dispose();
}
}
catch (Exception exception)
{
ex = exception;
e.Dispose();
}
if (ex != null)
{
try { observer.OnError(ex); }
finally { Dispose(); }
return;
}
if (!hasNext)
{
if (lastException != null)
{
try { observer.OnError(lastException); }
finally { Dispose(); }
}
else
{
try { observer.OnCompleted(); }
finally { Dispose(); }
}
return;
}
var source = current;
var d = new SingleAssignmentDisposable();
subscription.Disposable = d;
d.Disposable = source.Subscribe(this);
}
}
public override void OnNext(T value)
{
base.observer.OnNext(value);
}
public override void OnError(Exception error)
{
lastException = error;
nextSelf();
}
public override void OnCompleted()
{
try { observer.OnCompleted(); }
finally { Dispose(); }
return;
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 404a684db151ca34f8258c6fb373db8d
timeCreated: 1455373898
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 64910ffa78510ee48b3a395ee5b2cfe1
timeCreated: 1455373899
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,142 @@
using System;
using System.Collections.Generic;
namespace UniRx.Operators
{
// needs to more improvement
internal class ConcatObservable<T> : OperatorObservableBase<T>
{
readonly IEnumerable<IObservable<T>> sources;
public ConcatObservable(IEnumerable<IObservable<T>> sources)
: base(true)
{
this.sources = sources;
}
public IObservable<T> Combine(IEnumerable<IObservable<T>> combineSources)
{
return new ConcatObservable<T>(CombineSources(this.sources, combineSources));
}
static IEnumerable<IObservable<T>> CombineSources(IEnumerable<IObservable<T>> first, IEnumerable<IObservable<T>> second)
{
foreach (var item in first)
{
yield return item;
}
foreach (var item in second)
{
yield return item;
}
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
return new Concat(this, observer, cancel).Run();
}
class Concat : OperatorObserverBase<T, T>
{
readonly ConcatObservable<T> parent;
readonly object gate = new object();
bool isDisposed;
IEnumerator<IObservable<T>> e;
SerialDisposable subscription;
Action nextSelf;
public Concat(ConcatObservable<T> parent, IObserver<T> observer, IDisposable cancel)
: base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
isDisposed = false;
e = parent.sources.GetEnumerator();
subscription = new SerialDisposable();
var schedule = Scheduler.DefaultSchedulers.TailRecursion.Schedule(RecursiveRun);
return StableCompositeDisposable.Create(schedule, subscription, Disposable.Create(() =>
{
lock (gate)
{
this.isDisposed = true;
this.e.Dispose();
}
}));
}
void RecursiveRun(Action self)
{
lock (gate)
{
this.nextSelf = self;
if (isDisposed) return;
var current = default(IObservable<T>);
var hasNext = false;
var ex = default(Exception);
try
{
hasNext = e.MoveNext();
if (hasNext)
{
current = e.Current;
if (current == null) throw new InvalidOperationException("sequence is null.");
}
else
{
e.Dispose();
}
}
catch (Exception exception)
{
ex = exception;
e.Dispose();
}
if (ex != null)
{
try { observer.OnError(ex); }
finally { Dispose(); }
return;
}
if (!hasNext)
{
try { observer.OnCompleted(); }
finally { Dispose(); }
return;
}
var source = current;
var d = new SingleAssignmentDisposable();
subscription.Disposable = d;
d.Disposable = source.Subscribe(this);
}
}
public override void OnNext(T value)
{
base.observer.OnNext(value);
}
public override void OnError(Exception error)
{
try { observer.OnError(error); }
finally { Dispose(); }
}
public override void OnCompleted()
{
this.nextSelf();
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 740c2691a7e434f439abfdcac75ea809
timeCreated: 1455373899
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,77 @@
using System;
namespace UniRx.Operators
{
internal class ContinueWithObservable<TSource, TResult> : OperatorObservableBase<TResult>
{
readonly IObservable<TSource> source;
readonly Func<TSource, IObservable<TResult>> selector;
public ContinueWithObservable(IObservable<TSource> source, Func<TSource, IObservable<TResult>> selector)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.selector = selector;
}
protected override IDisposable SubscribeCore(IObserver<TResult> observer, IDisposable cancel)
{
return new ContinueWith(this, observer, cancel).Run();
}
class ContinueWith : OperatorObserverBase<TSource, TResult>
{
readonly ContinueWithObservable<TSource, TResult> parent;
readonly SerialDisposable serialDisposable = new SerialDisposable();
bool seenValue;
TSource lastValue;
public ContinueWith(ContinueWithObservable<TSource, TResult> parent, IObserver<TResult> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
var sourceDisposable = new SingleAssignmentDisposable();
serialDisposable.Disposable = sourceDisposable;
sourceDisposable.Disposable = parent.source.Subscribe(this);
return serialDisposable;
}
public override void OnNext(TSource value)
{
this.seenValue = true;
this.lastValue = value;
}
public override void OnError(Exception error)
{
try { observer.OnError(error); } finally { Dispose(); };
}
public override void OnCompleted()
{
if (seenValue)
{
try
{
var v = parent.selector(lastValue);
// dispose source subscription
serialDisposable.Disposable = v.Subscribe(observer);
}
catch (Exception error)
{
OnError(error);
}
}
else
{
try { observer.OnCompleted(); } finally { Dispose(); };
}
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: bea59b3eb246d244a99183eeb7f3bad4
timeCreated: 1455373901
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,156 @@
using System;
namespace UniRx.Operators
{
internal class CreateObservable<T> : OperatorObservableBase<T>
{
readonly Func<IObserver<T>, IDisposable> subscribe;
public CreateObservable(Func<IObserver<T>, IDisposable> subscribe)
: base(true) // fail safe
{
this.subscribe = subscribe;
}
public CreateObservable(Func<IObserver<T>, IDisposable> subscribe, bool isRequiredSubscribeOnCurrentThread)
: base(isRequiredSubscribeOnCurrentThread)
{
this.subscribe = subscribe;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
observer = new Create(observer, cancel);
return subscribe(observer) ?? Disposable.Empty;
}
class Create : OperatorObserverBase<T, T>
{
public Create(IObserver<T> observer, IDisposable cancel) : base(observer, cancel)
{
}
public override void OnNext(T value)
{
base.observer.OnNext(value);
}
public override void OnError(Exception error)
{
try { observer.OnError(error); }
finally { Dispose(); }
}
public override void OnCompleted()
{
try { observer.OnCompleted(); }
finally { Dispose(); }
}
}
}
internal class CreateObservable<T, TState> : OperatorObservableBase<T>
{
readonly TState state;
readonly Func<TState, IObserver<T>, IDisposable> subscribe;
public CreateObservable(TState state, Func<TState, IObserver<T>, IDisposable> subscribe)
: base(true) // fail safe
{
this.state = state;
this.subscribe = subscribe;
}
public CreateObservable(TState state, Func<TState, IObserver<T>, IDisposable> subscribe, bool isRequiredSubscribeOnCurrentThread)
: base(isRequiredSubscribeOnCurrentThread)
{
this.state = state;
this.subscribe = subscribe;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
observer = new Create(observer, cancel);
return subscribe(state, observer) ?? Disposable.Empty;
}
class Create : OperatorObserverBase<T, T>
{
public Create(IObserver<T> observer, IDisposable cancel) : base(observer, cancel)
{
}
public override void OnNext(T value)
{
base.observer.OnNext(value);
}
public override void OnError(Exception error)
{
try { observer.OnError(error); }
finally { Dispose(); }
}
public override void OnCompleted()
{
try { observer.OnCompleted(); }
finally { Dispose(); }
}
}
}
internal class CreateSafeObservable<T> : OperatorObservableBase<T>
{
readonly Func<IObserver<T>, IDisposable> subscribe;
public CreateSafeObservable(Func<IObserver<T>, IDisposable> subscribe)
: base(true) // fail safe
{
this.subscribe = subscribe;
}
public CreateSafeObservable(Func<IObserver<T>, IDisposable> subscribe, bool isRequiredSubscribeOnCurrentThread)
: base(isRequiredSubscribeOnCurrentThread)
{
this.subscribe = subscribe;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
observer = new CreateSafe(observer, cancel);
return subscribe(observer) ?? Disposable.Empty;
}
class CreateSafe : OperatorObserverBase<T, T>
{
public CreateSafe(IObserver<T> observer, IDisposable cancel) : base(observer, cancel)
{
}
public override void OnNext(T value)
{
try
{
base.observer.OnNext(value);
}
catch
{
Dispose(); // safe
throw;
}
}
public override void OnError(Exception error)
{
try { observer.OnError(error); }
finally { Dispose(); }
}
public override void OnCompleted()
{
try { observer.OnCompleted(); }
finally { Dispose(); }
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: cae9e62bf5eb3dc4e9d93cf6ff606052
timeCreated: 1455373901
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,58 @@
using System;
using UniRx.Operators;
namespace UniRx.Operators
{
internal class DefaultIfEmptyObservable<T> : OperatorObservableBase<T>
{
readonly IObservable<T> source;
readonly T defaultValue;
public DefaultIfEmptyObservable(IObservable<T> source, T defaultValue)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.defaultValue = defaultValue;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
return source.Subscribe(new DefaultIfEmpty(this, observer, cancel));
}
class DefaultIfEmpty : OperatorObserverBase<T, T>
{
readonly DefaultIfEmptyObservable<T> parent;
bool hasValue;
public DefaultIfEmpty(DefaultIfEmptyObservable<T> parent, IObserver<T> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
this.hasValue = false;
}
public override void OnNext(T value)
{
hasValue = true;
observer.OnNext(value);
}
public override void OnError(Exception error)
{
try { observer.OnError(error); }
finally { Dispose(); }
}
public override void OnCompleted()
{
if (!hasValue)
{
observer.OnNext(parent.defaultValue);
}
try { observer.OnCompleted(); }
finally { Dispose(); }
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 551075cda284fbc489824d153743b1e6
timeCreated: 1455373899
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,64 @@
using System;
namespace UniRx.Operators
{
internal class DeferObservable<T> : OperatorObservableBase<T>
{
readonly Func<IObservable<T>> observableFactory;
public DeferObservable(Func<IObservable<T>> observableFactory)
: base(false)
{
this.observableFactory = observableFactory;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
observer = new Defer(observer, cancel);
IObservable<T> source;
try
{
source = observableFactory();
}
catch (Exception ex)
{
source = Observable.Throw<T>(ex);
}
return source.Subscribe(observer);
}
class Defer : OperatorObserverBase<T, T>
{
public Defer(IObserver<T> observer, IDisposable cancel) : base(observer, cancel)
{
}
public override void OnNext(T value)
{
try
{
base.observer.OnNext(value);
}
catch
{
Dispose();
throw;
}
}
public override void OnError(Exception error)
{
try { observer.OnError(error); }
finally { Dispose(); }
}
public override void OnCompleted()
{
try { observer.OnCompleted(); }
finally { Dispose(); }
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 15ca418b98836d943864b1e8b82f6658
timeCreated: 1455373897
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,227 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UniRx.Operators
{
internal class DelayObservable<T> : OperatorObservableBase<T>
{
readonly IObservable<T> source;
readonly TimeSpan dueTime;
readonly IScheduler scheduler;
public DelayObservable(IObservable<T> source, TimeSpan dueTime, IScheduler scheduler)
: base(scheduler == Scheduler.CurrentThread || source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.dueTime = dueTime;
this.scheduler = scheduler;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
return new Delay(this, observer, cancel).Run();
}
class Delay : OperatorObserverBase<T, T>
{
readonly DelayObservable<T> parent;
readonly object gate = new object();
bool hasFailed;
bool running;
bool active;
Exception exception;
Queue<Timestamped<T>> queue;
bool onCompleted;
DateTimeOffset completeAt;
IDisposable sourceSubscription;
TimeSpan delay;
bool ready;
SerialDisposable cancelable;
public Delay(DelayObservable<T> parent, IObserver<T> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
cancelable = new SerialDisposable();
active = false;
running = false;
queue = new Queue<Timestamped<T>>();
onCompleted = false;
completeAt = default(DateTimeOffset);
hasFailed = false;
exception = default(Exception);
ready = true;
delay = Scheduler.Normalize(parent.dueTime);
var _sourceSubscription = new SingleAssignmentDisposable();
sourceSubscription = _sourceSubscription; // assign to field
_sourceSubscription.Disposable = parent.source.Subscribe(this);
return StableCompositeDisposable.Create(sourceSubscription, cancelable);
}
public override void OnNext(T value)
{
var next = parent.scheduler.Now.Add(delay);
var shouldRun = false;
lock (gate)
{
queue.Enqueue(new Timestamped<T>(value, next));
shouldRun = ready && !active;
active = true;
}
if (shouldRun)
{
cancelable.Disposable = parent.scheduler.Schedule(delay, DrainQueue);
}
}
public override void OnError(Exception error)
{
sourceSubscription.Dispose();
var shouldRun = false;
lock (gate)
{
queue.Clear();
exception = error;
hasFailed = true;
shouldRun = !running;
}
if (shouldRun)
{
try { base.observer.OnError(error); } finally { Dispose(); }
}
}
public override void OnCompleted()
{
sourceSubscription.Dispose();
var next = parent.scheduler.Now.Add(delay);
var shouldRun = false;
lock (gate)
{
completeAt = next;
onCompleted = true;
shouldRun = ready && !active;
active = true;
}
if (shouldRun)
{
cancelable.Disposable = parent.scheduler.Schedule(delay, DrainQueue);
}
}
void DrainQueue(Action<TimeSpan> recurse)
{
lock (gate)
{
if (hasFailed) return;
running = true;
}
var shouldYield = false;
while (true)
{
var hasFailed = false;
var error = default(Exception);
var hasValue = false;
var value = default(T);
var hasCompleted = false;
var shouldRecurse = false;
var recurseDueTime = default(TimeSpan);
lock (gate)
{
if (hasFailed)
{
error = exception;
hasFailed = true;
running = false;
}
else
{
if (queue.Count > 0)
{
var nextDue = queue.Peek().Timestamp;
if (nextDue.CompareTo(parent.scheduler.Now) <= 0 && !shouldYield)
{
value = queue.Dequeue().Value;
hasValue = true;
}
else
{
shouldRecurse = true;
recurseDueTime = Scheduler.Normalize(nextDue.Subtract(parent.scheduler.Now));
running = false;
}
}
else if (onCompleted)
{
if (completeAt.CompareTo(parent.scheduler.Now) <= 0 && !shouldYield)
{
hasCompleted = true;
}
else
{
shouldRecurse = true;
recurseDueTime = Scheduler.Normalize(completeAt.Subtract(parent.scheduler.Now));
running = false;
}
}
else
{
running = false;
active = false;
}
}
}
if (hasValue)
{
base.observer.OnNext(value);
shouldYield = true;
}
else
{
if (hasCompleted)
{
try { base.observer.OnCompleted(); } finally { Dispose(); }
}
else if (hasFailed)
{
try { base.observer.OnError(error); } finally { Dispose(); }
}
else if (shouldRecurse)
{
recurse(recurseDueTime);
}
return;
}
}
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 2af9c507ce062994a904e4b5565b49c0
timeCreated: 1455373898
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
namespace UniRx.Operators
{
internal class DelaySubscriptionObservable<T> : OperatorObservableBase<T>
{
readonly IObservable<T> source;
readonly IScheduler scheduler;
readonly TimeSpan? dueTimeT;
readonly DateTimeOffset? dueTimeD;
public DelaySubscriptionObservable(IObservable<T> source,TimeSpan dueTime, IScheduler scheduler)
: base(scheduler == Scheduler.CurrentThread || source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.scheduler = scheduler;
this.dueTimeT = dueTime;
}
public DelaySubscriptionObservable(IObservable<T> source, DateTimeOffset dueTime, IScheduler scheduler)
: base(scheduler == Scheduler.CurrentThread || source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.scheduler = scheduler;
this.dueTimeD = dueTime;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
if (dueTimeT != null)
{
var d = new MultipleAssignmentDisposable();
var dt = Scheduler.Normalize(dueTimeT.Value);
d.Disposable = scheduler.Schedule(dt, () =>
{
d.Disposable = source.Subscribe(observer);
});
return d;
}
else
{
var d = new MultipleAssignmentDisposable();
d.Disposable = scheduler.Schedule(dueTimeD.Value, () =>
{
d.Disposable = source.Subscribe(observer);
});
return d;
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 4f532fc776d5298439cb8f03d52e1211
timeCreated: 1455373899
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,66 @@
using System;
namespace UniRx.Operators
{
internal class DematerializeObservable<T> : OperatorObservableBase<T>
{
readonly IObservable<Notification<T>> source;
public DematerializeObservable(IObservable<Notification<T>> source)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
return new Dematerialize(this, observer, cancel).Run();
}
class Dematerialize : OperatorObserverBase<Notification<T>, T>
{
readonly DematerializeObservable<T> parent;
public Dematerialize(DematerializeObservable<T> parent, IObserver<T> observer, IDisposable cancel)
: base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
return parent.source.Subscribe(this);
}
public override void OnNext(Notification<T> value)
{
switch (value.Kind)
{
case NotificationKind.OnNext:
observer.OnNext(value.Value);
break;
case NotificationKind.OnError:
try { observer.OnError(value.Exception); }
finally { Dispose(); }
break;
case NotificationKind.OnCompleted:
try { observer.OnCompleted(); }
finally { Dispose(); }
break;
default:
break;
}
}
public override void OnError(Exception error)
{
try { observer.OnError(error); } finally { Dispose(); }
}
public override void OnCompleted()
{
try { observer.OnCompleted(); } finally { Dispose(); }
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 80682be7e41afb44581208534f226d38
timeCreated: 1455373899
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,133 @@
using System;
using System.Collections.Generic;
namespace UniRx.Operators
{
internal class DistinctObservable<T> : OperatorObservableBase<T>
{
readonly IObservable<T> source;
readonly IEqualityComparer<T> comparer;
public DistinctObservable(IObservable<T> source, IEqualityComparer<T> comparer)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.comparer = comparer;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
return source.Subscribe(new Distinct(this, observer, cancel));
}
class Distinct : OperatorObserverBase<T, T>
{
readonly HashSet<T> hashSet;
public Distinct(DistinctObservable<T> parent, IObserver<T> observer, IDisposable cancel)
: base(observer, cancel)
{
hashSet = (parent.comparer == null)
? new HashSet<T>()
: new HashSet<T>(parent.comparer);
}
public override void OnNext(T value)
{
var key = default(T);
var isAdded = false;
try
{
key = value;
isAdded = hashSet.Add(key);
}
catch (Exception exception)
{
try { observer.OnError(exception); } finally { Dispose(); }
return;
}
if (isAdded)
{
observer.OnNext(value);
}
}
public override void OnError(Exception error)
{
try { observer.OnError(error); } finally { Dispose(); }
}
public override void OnCompleted()
{
try { observer.OnCompleted(); } finally { Dispose(); }
}
}
}
internal class DistinctObservable<T, TKey> : OperatorObservableBase<T>
{
readonly IObservable<T> source;
readonly IEqualityComparer<TKey> comparer;
readonly Func<T, TKey> keySelector;
public DistinctObservable(IObservable<T> source, Func<T, TKey> keySelector, IEqualityComparer<TKey> comparer)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.comparer = comparer;
this.keySelector = keySelector;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
return source.Subscribe(new Distinct(this, observer, cancel));
}
class Distinct : OperatorObserverBase<T, T>
{
readonly DistinctObservable<T, TKey> parent;
readonly HashSet<TKey> hashSet;
public Distinct(DistinctObservable<T, TKey> parent, IObserver<T> observer, IDisposable cancel)
: base(observer, cancel)
{
this.parent = parent;
hashSet = (parent.comparer == null)
? new HashSet<TKey>()
: new HashSet<TKey>(parent.comparer);
}
public override void OnNext(T value)
{
var key = default(TKey);
var isAdded = false;
try
{
key = parent.keySelector(value);
isAdded = hashSet.Add(key);
}
catch (Exception exception)
{
try { observer.OnError(exception); } finally { Dispose(); }
return;
}
if (isAdded)
{
observer.OnNext(value);
}
}
public override void OnError(Exception error)
{
try { observer.OnError(error); } finally { Dispose(); }
}
public override void OnCompleted()
{
try { observer.OnCompleted(); } finally { Dispose(); }
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 376a7ed430bff5c4b860af4d23ab6b79
timeCreated: 1455373898
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,165 @@
using System;
using System.Collections.Generic;
namespace UniRx.Operators
{
internal class DistinctUntilChangedObservable<T> : OperatorObservableBase<T>
{
readonly IObservable<T> source;
readonly IEqualityComparer<T> comparer;
public DistinctUntilChangedObservable(IObservable<T> source, IEqualityComparer<T> comparer)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.comparer = comparer;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
return source.Subscribe(new DistinctUntilChanged(this, observer, cancel));
}
class DistinctUntilChanged : OperatorObserverBase<T, T>
{
readonly DistinctUntilChangedObservable<T> parent;
bool isFirst = true;
T prevKey = default(T);
public DistinctUntilChanged(DistinctUntilChangedObservable<T> parent, IObserver<T> observer, IDisposable cancel)
: base(observer, cancel)
{
this.parent = parent;
}
public override void OnNext(T value)
{
T currentKey;
try
{
currentKey = value;
}
catch (Exception exception)
{
try { observer.OnError(exception); } finally { Dispose(); }
return;
}
var sameKey = false;
if (isFirst)
{
isFirst = false;
}
else
{
try
{
sameKey = parent.comparer.Equals(currentKey, prevKey);
}
catch (Exception ex)
{
try { observer.OnError(ex); } finally { Dispose(); }
return;
}
}
if (!sameKey)
{
prevKey = currentKey;
observer.OnNext(value);
}
}
public override void OnError(Exception error)
{
try { observer.OnError(error); } finally { Dispose(); }
}
public override void OnCompleted()
{
try { observer.OnCompleted(); } finally { Dispose(); }
}
}
}
internal class DistinctUntilChangedObservable<T, TKey> : OperatorObservableBase<T>
{
readonly IObservable<T> source;
readonly IEqualityComparer<TKey> comparer;
readonly Func<T, TKey> keySelector;
public DistinctUntilChangedObservable(IObservable<T> source, Func<T, TKey> keySelector, IEqualityComparer<TKey> comparer)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.comparer = comparer;
this.keySelector = keySelector;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
return source.Subscribe(new DistinctUntilChanged(this, observer, cancel));
}
class DistinctUntilChanged : OperatorObserverBase<T, T>
{
readonly DistinctUntilChangedObservable<T, TKey> parent;
bool isFirst = true;
TKey prevKey = default(TKey);
public DistinctUntilChanged(DistinctUntilChangedObservable<T, TKey> parent, IObserver<T> observer, IDisposable cancel)
: base(observer, cancel)
{
this.parent = parent;
}
public override void OnNext(T value)
{
TKey currentKey;
try
{
currentKey = parent.keySelector(value);
}
catch (Exception exception)
{
try { observer.OnError(exception); } finally { Dispose(); }
return;
}
var sameKey = false;
if (isFirst)
{
isFirst = false;
}
else
{
try
{
sameKey = parent.comparer.Equals(currentKey, prevKey);
}
catch (Exception ex)
{
try { observer.OnError(ex); } finally { Dispose(); }
return;
}
}
if (!sameKey)
{
prevKey = currentKey;
observer.OnNext(value);
}
}
public override void OnError(Exception error)
{
try { observer.OnError(error); } finally { Dispose(); }
}
public override void OnCompleted()
{
try { observer.OnCompleted(); } finally { Dispose(); }
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: a09c4b58f60c22342871c30eaf589f6c
timeCreated: 1455373900
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,477 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UniRx.Operators
{
// Do, DoOnError, DoOnCompleted, DoOnTerminate, DoOnSubscribe, DoOnCancel
internal class DoObservable<T> : OperatorObservableBase<T>
{
readonly IObservable<T> source;
readonly Action<T> onNext;
readonly Action<Exception> onError;
readonly Action onCompleted;
public DoObservable(IObservable<T> source, Action<T> onNext, Action<Exception> onError, Action onCompleted)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.onNext = onNext;
this.onError = onError;
this.onCompleted = onCompleted;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
return new Do(this, observer, cancel).Run();
}
class Do : OperatorObserverBase<T, T>
{
readonly DoObservable<T> parent;
public Do(DoObservable<T> parent, IObserver<T> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
return parent.source.Subscribe(this);
}
public override void OnNext(T value)
{
try
{
parent.onNext(value);
}
catch (Exception ex)
{
try { observer.OnError(ex); } finally { Dispose(); };
return;
}
base.observer.OnNext(value);
}
public override void OnError(Exception error)
{
try
{
parent.onError(error);
}
catch (Exception ex)
{
try { observer.OnError(ex); } finally { Dispose(); };
return;
}
try { observer.OnError(error); } finally { Dispose(); };
}
public override void OnCompleted()
{
try
{
parent.onCompleted();
}
catch (Exception ex)
{
base.observer.OnError(ex);
Dispose();
return;
}
try { observer.OnCompleted(); } finally { Dispose(); };
}
}
}
internal class DoObserverObservable<T> : OperatorObservableBase<T>
{
readonly IObservable<T> source;
readonly IObserver<T> observer;
public DoObserverObservable(IObservable<T> source, IObserver<T> observer)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.observer = observer;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
return new Do(this, observer, cancel).Run();
}
class Do : OperatorObserverBase<T, T>
{
readonly DoObserverObservable<T> parent;
public Do(DoObserverObservable<T> parent, IObserver<T> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
return parent.source.Subscribe(this);
}
public override void OnNext(T value)
{
try
{
parent.observer.OnNext(value);
}
catch (Exception ex)
{
try { observer.OnError(ex); }
finally { Dispose(); }
return;
}
base.observer.OnNext(value);
}
public override void OnError(Exception error)
{
try
{
parent.observer.OnError(error);
}
catch (Exception ex)
{
try { observer.OnError(ex); }
finally { Dispose(); }
return;
}
try { observer.OnError(error); }
finally { Dispose(); }
}
public override void OnCompleted()
{
try
{
parent.observer.OnCompleted();
}
catch (Exception ex)
{
try { observer.OnError(ex); }
finally { Dispose(); }
return;
}
try { observer.OnCompleted(); }
finally { Dispose(); }
}
}
}
internal class DoOnErrorObservable<T> : OperatorObservableBase<T>
{
readonly IObservable<T> source;
readonly Action<Exception> onError;
public DoOnErrorObservable(IObservable<T> source, Action<Exception> onError)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.onError = onError;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
return new DoOnError(this, observer, cancel).Run();
}
class DoOnError : OperatorObserverBase<T, T>
{
readonly DoOnErrorObservable<T> parent;
public DoOnError(DoOnErrorObservable<T> parent, IObserver<T> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
return parent.source.Subscribe(this);
}
public override void OnNext(T value)
{
base.observer.OnNext(value);
}
public override void OnError(Exception error)
{
try
{
parent.onError(error);
}
catch (Exception ex)
{
try { observer.OnError(ex); }
finally { Dispose(); }
return;
}
try { observer.OnError(error); }
finally { Dispose(); }
}
public override void OnCompleted()
{
try { observer.OnCompleted(); }
finally { Dispose(); }
}
}
}
internal class DoOnCompletedObservable<T> : OperatorObservableBase<T>
{
readonly IObservable<T> source;
readonly Action onCompleted;
public DoOnCompletedObservable(IObservable<T> source, Action onCompleted)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.onCompleted = onCompleted;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
return new DoOnCompleted(this, observer, cancel).Run();
}
class DoOnCompleted : OperatorObserverBase<T, T>
{
readonly DoOnCompletedObservable<T> parent;
public DoOnCompleted(DoOnCompletedObservable<T> parent, IObserver<T> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
return parent.source.Subscribe(this);
}
public override void OnNext(T value)
{
base.observer.OnNext(value);
}
public override void OnError(Exception error)
{
try { observer.OnError(error); }
finally { Dispose(); }
}
public override void OnCompleted()
{
try
{
parent.onCompleted();
}
catch (Exception ex)
{
base.observer.OnError(ex);
Dispose();
return;
}
try { observer.OnCompleted(); } finally { Dispose(); };
}
}
}
internal class DoOnTerminateObservable<T> : OperatorObservableBase<T>
{
readonly IObservable<T> source;
readonly Action onTerminate;
public DoOnTerminateObservable(IObservable<T> source, Action onTerminate)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.onTerminate = onTerminate;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
return new DoOnTerminate(this, observer, cancel).Run();
}
class DoOnTerminate : OperatorObserverBase<T, T>
{
readonly DoOnTerminateObservable<T> parent;
public DoOnTerminate(DoOnTerminateObservable<T> parent, IObserver<T> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
return parent.source.Subscribe(this);
}
public override void OnNext(T value)
{
base.observer.OnNext(value);
}
public override void OnError(Exception error)
{
try
{
parent.onTerminate();
}
catch (Exception ex)
{
try { observer.OnError(ex); }
finally { Dispose(); }
return;
}
try { observer.OnError(error); } finally { Dispose(); };
}
public override void OnCompleted()
{
try
{
parent.onTerminate();
}
catch (Exception ex)
{
base.observer.OnError(ex);
Dispose();
return;
}
try { observer.OnCompleted(); } finally { Dispose(); };
}
}
}
internal class DoOnSubscribeObservable<T> : OperatorObservableBase<T>
{
readonly IObservable<T> source;
readonly Action onSubscribe;
public DoOnSubscribeObservable(IObservable<T> source, Action onSubscribe)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.onSubscribe = onSubscribe;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
return new DoOnSubscribe(this, observer, cancel).Run();
}
class DoOnSubscribe : OperatorObserverBase<T, T>
{
readonly DoOnSubscribeObservable<T> parent;
public DoOnSubscribe(DoOnSubscribeObservable<T> parent, IObserver<T> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
try
{
parent.onSubscribe();
}
catch (Exception ex)
{
try { observer.OnError(ex); }
finally { Dispose(); }
return Disposable.Empty;
}
return parent.source.Subscribe(this);
}
public override void OnNext(T value)
{
base.observer.OnNext(value);
}
public override void OnError(Exception error)
{
try { observer.OnError(error); } finally { Dispose(); }
}
public override void OnCompleted()
{
try { observer.OnCompleted(); } finally { Dispose(); }
}
}
}
internal class DoOnCancelObservable<T> : OperatorObservableBase<T>
{
readonly IObservable<T> source;
readonly Action onCancel;
public DoOnCancelObservable(IObservable<T> source, Action onCancel)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.onCancel = onCancel;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
return new DoOnCancel(this, observer, cancel).Run();
}
class DoOnCancel : OperatorObserverBase<T, T>
{
readonly DoOnCancelObservable<T> parent;
bool isCompletedCall = false;
public DoOnCancel(DoOnCancelObservable<T> parent, IObserver<T> observer, IDisposable cancel)
: base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
return StableCompositeDisposable.Create(parent.source.Subscribe(this), Disposable.Create(() =>
{
if (!isCompletedCall)
{
parent.onCancel();
}
}));
}
public override void OnNext(T value)
{
base.observer.OnNext(value);
}
public override void OnError(Exception error)
{
isCompletedCall = true;
try { observer.OnError(error); } finally { Dispose(); };
}
public override void OnCompleted()
{
isCompletedCall = true;
try { observer.OnCompleted(); } finally { Dispose(); };
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 8f99ae8870195e34b8618451a95818e0
timeCreated: 1455373900
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,83 @@
using System;
namespace UniRx.Operators
{
internal class EmptyObservable<T> : OperatorObservableBase<T>
{
readonly IScheduler scheduler;
public EmptyObservable(IScheduler scheduler)
: base(false)
{
this.scheduler = scheduler;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
observer = new Empty(observer, cancel);
if (scheduler == Scheduler.Immediate)
{
observer.OnCompleted();
return Disposable.Empty;
}
else
{
return scheduler.Schedule(observer.OnCompleted);
}
}
class Empty : OperatorObserverBase<T, T>
{
public Empty(IObserver<T> observer, IDisposable cancel) : base(observer, cancel)
{
}
public override void OnNext(T value)
{
try
{
base.observer.OnNext(value);
}
catch
{
Dispose();
throw;
}
}
public override void OnError(Exception error)
{
try { observer.OnError(error); }
finally { Dispose(); }
}
public override void OnCompleted()
{
try { observer.OnCompleted(); }
finally { Dispose(); }
}
}
}
internal class ImmutableEmptyObservable<T> : IObservable<T>, IOptimizedObservable<T>
{
internal static ImmutableEmptyObservable<T> Instance = new ImmutableEmptyObservable<T>();
ImmutableEmptyObservable()
{
}
public bool IsRequiredSubscribeOnCurrentThread()
{
return false;
}
public IDisposable Subscribe(IObserver<T> observer)
{
observer.OnCompleted();
return Disposable.Empty;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 9e9a7050a289d3a4aa17cba89e085135
timeCreated: 1455373900
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,68 @@
using System;
namespace UniRx.Operators
{
internal class FinallyObservable<T> : OperatorObservableBase<T>
{
readonly IObservable<T> source;
readonly Action finallyAction;
public FinallyObservable(IObservable<T> source, Action finallyAction)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.finallyAction = finallyAction;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
return new Finally(this, observer, cancel).Run();
}
class Finally : OperatorObserverBase<T, T>
{
readonly FinallyObservable<T> parent;
public Finally(FinallyObservable<T> parent, IObserver<T> observer, IDisposable cancel)
: base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
IDisposable subscription;
try
{
subscription = parent.source.Subscribe(this);
}
catch
{
// This behaviour is not same as .NET Official Rx
parent.finallyAction();
throw;
}
return StableCompositeDisposable.Create(subscription, Disposable.Create(() =>
{
parent.finallyAction();
}));
}
public override void OnNext(T value)
{
base.observer.OnNext(value);
}
public override void OnError(Exception error)
{
try { observer.OnError(error); } finally { Dispose(); };
}
public override void OnCompleted()
{
try { observer.OnCompleted(); } finally { Dispose(); };
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 9ce919d8f2acf2b47a932e850e399d3a
timeCreated: 1455373900
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,166 @@
using System;
using UniRx.Operators;
namespace UniRx.Operators
{
internal class FirstObservable<T> : OperatorObservableBase<T>
{
readonly IObservable<T> source;
readonly bool useDefault;
readonly Func<T, bool> predicate;
public FirstObservable(IObservable<T> source, bool useDefault)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.useDefault = useDefault;
}
public FirstObservable(IObservable<T> source, Func<T, bool> predicate, bool useDefault)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.predicate = predicate;
this.useDefault = useDefault;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
if (predicate == null)
{
return source.Subscribe(new First(this, observer, cancel));
}
else
{
return source.Subscribe(new First_(this, observer, cancel));
}
}
class First : OperatorObserverBase<T, T>
{
readonly FirstObservable<T> parent;
bool notPublished;
public First(FirstObservable<T> parent, IObserver<T> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
this.notPublished = true;
}
public override void OnNext(T value)
{
if (notPublished)
{
notPublished = false;
observer.OnNext(value);
try { observer.OnCompleted(); }
finally { Dispose(); }
return;
}
}
public override void OnError(Exception error)
{
try { observer.OnError(error); }
finally { Dispose(); }
}
public override void OnCompleted()
{
if (parent.useDefault)
{
if (notPublished)
{
observer.OnNext(default(T));
}
try { observer.OnCompleted(); }
finally { Dispose(); }
}
else
{
if (notPublished)
{
try { observer.OnError(new InvalidOperationException("sequence is empty")); }
finally { Dispose(); }
}
else
{
try { observer.OnCompleted(); }
finally { Dispose(); }
}
}
}
}
// with predicate
class First_ : OperatorObserverBase<T, T>
{
readonly FirstObservable<T> parent;
bool notPublished;
public First_(FirstObservable<T> parent, IObserver<T> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
this.notPublished = true;
}
public override void OnNext(T value)
{
if (notPublished)
{
bool isPassed;
try
{
isPassed = parent.predicate(value);
}
catch (Exception ex)
{
try { observer.OnError(ex); }
finally { Dispose(); }
return;
}
if (isPassed)
{
notPublished = false;
observer.OnNext(value);
try { observer.OnCompleted(); }
finally { Dispose(); }
}
}
}
public override void OnError(Exception error)
{
try { observer.OnError(error); }
finally { Dispose(); }
}
public override void OnCompleted()
{
if (parent.useDefault)
{
if (notPublished)
{
observer.OnNext(default(T));
}
try { observer.OnCompleted(); }
finally { Dispose(); }
}
else
{
if (notPublished)
{
try { observer.OnError(new InvalidOperationException("sequence is empty")); }
finally { Dispose(); }
}
else
{
try { observer.OnCompleted(); }
finally { Dispose(); }
}
}
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 8e3093220aeb1d54faa3fca9fe0af6c0
timeCreated: 1455373900
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,116 @@
using System;
using UniRx.Operators;
namespace UniRx.Operators
{
internal class ForEachAsyncObservable<T> : OperatorObservableBase<Unit>
{
readonly IObservable<T> source;
readonly Action<T> onNext;
readonly Action<T, int> onNextWithIndex;
public ForEachAsyncObservable(IObservable<T> source, Action<T> onNext)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.onNext = onNext;
}
public ForEachAsyncObservable(IObservable<T> source, Action<T, int> onNext)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.onNextWithIndex = onNext;
}
protected override IDisposable SubscribeCore(IObserver<Unit> observer, IDisposable cancel)
{
if (onNext != null)
{
return source.Subscribe(new ForEachAsync(this, observer, cancel));
}
else
{
return source.Subscribe(new ForEachAsync_(this, observer, cancel));
}
}
class ForEachAsync : OperatorObserverBase<T, Unit>
{
readonly ForEachAsyncObservable<T> parent;
public ForEachAsync(ForEachAsyncObservable<T> parent, IObserver<Unit> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
}
public override void OnNext(T value)
{
try
{
parent.onNext(value);
}
catch (Exception ex)
{
try { observer.OnError(ex); }
finally { Dispose(); }
return;
}
}
public override void OnError(Exception error)
{
try { observer.OnError(error); }
finally { Dispose(); }
}
public override void OnCompleted()
{
observer.OnNext(Unit.Default);
try { observer.OnCompleted(); }
finally { Dispose(); }
}
}
// with index
class ForEachAsync_ : OperatorObserverBase<T, Unit>
{
readonly ForEachAsyncObservable<T> parent;
int index = 0;
public ForEachAsync_(ForEachAsyncObservable<T> parent, IObserver<Unit> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
}
public override void OnNext(T value)
{
try
{
parent.onNextWithIndex(value, index++);
}
catch (Exception ex)
{
try { observer.OnError(ex); }
finally { Dispose(); }
return;
}
}
public override void OnError(Exception error)
{
try { observer.OnError(error); }
finally { Dispose(); }
}
public override void OnCompleted()
{
observer.OnNext(Unit.Default);
try { observer.OnCompleted(); }
finally { Dispose(); }
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 5b66ecd2e5290bc4eb8c78a1ccc2d009
timeCreated: 1455373899
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,323 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UniRx.Operators
{
// FromEvent, FromEventPattern
internal class FromEventPatternObservable<TDelegate, TEventArgs> : OperatorObservableBase<EventPattern<TEventArgs>>
where TEventArgs : EventArgs
{
readonly Func<EventHandler<TEventArgs>, TDelegate> conversion;
readonly Action<TDelegate> addHandler;
readonly Action<TDelegate> removeHandler;
public FromEventPatternObservable(Func<EventHandler<TEventArgs>, TDelegate> conversion, Action<TDelegate> addHandler, Action<TDelegate> removeHandler)
: base(false)
{
this.conversion = conversion;
this.addHandler = addHandler;
this.removeHandler = removeHandler;
}
protected override IDisposable SubscribeCore(IObserver<EventPattern<TEventArgs>> observer, IDisposable cancel)
{
var fe = new FromEventPattern(this, observer);
return fe.Register() ? fe : Disposable.Empty;
}
class FromEventPattern : IDisposable
{
readonly FromEventPatternObservable<TDelegate, TEventArgs> parent;
readonly IObserver<EventPattern<TEventArgs>> observer;
TDelegate handler;
public FromEventPattern(FromEventPatternObservable<TDelegate, TEventArgs> parent, IObserver<EventPattern<TEventArgs>> observer)
{
this.parent = parent;
this.observer = observer;
}
public bool Register()
{
handler = parent.conversion(OnNext);
try
{
parent.addHandler(handler);
}
catch (Exception ex)
{
observer.OnError(ex);
return false;
}
return true;
}
void OnNext(object sender, TEventArgs eventArgs)
{
observer.OnNext(new EventPattern<TEventArgs>(sender, eventArgs));
}
public void Dispose()
{
if (handler != null)
{
parent.removeHandler(handler);
handler = default(TDelegate);
}
}
}
}
internal class FromEventObservable<TDelegate> : OperatorObservableBase<Unit>
{
readonly Func<Action, TDelegate> conversion;
readonly Action<TDelegate> addHandler;
readonly Action<TDelegate> removeHandler;
public FromEventObservable(Func<Action, TDelegate> conversion, Action<TDelegate> addHandler, Action<TDelegate> removeHandler)
: base(false)
{
this.conversion = conversion;
this.addHandler = addHandler;
this.removeHandler = removeHandler;
}
protected override IDisposable SubscribeCore(IObserver<Unit> observer, IDisposable cancel)
{
var fe = new FromEvent(this, observer);
return fe.Register() ? fe : Disposable.Empty;
}
class FromEvent : IDisposable
{
readonly FromEventObservable<TDelegate> parent;
readonly IObserver<Unit> observer;
TDelegate handler;
public FromEvent(FromEventObservable<TDelegate> parent, IObserver<Unit> observer)
{
this.parent = parent;
this.observer = observer;
}
public bool Register()
{
handler = parent.conversion(OnNext);
try
{
parent.addHandler(handler);
}
catch (Exception ex)
{
observer.OnError(ex);
return false;
}
return true;
}
void OnNext()
{
observer.OnNext(Unit.Default);
}
public void Dispose()
{
if (handler != null)
{
parent.removeHandler(handler);
handler = default(TDelegate);
}
}
}
}
internal class FromEventObservable<TDelegate, TEventArgs> : OperatorObservableBase<TEventArgs>
{
readonly Func<Action<TEventArgs>, TDelegate> conversion;
readonly Action<TDelegate> addHandler;
readonly Action<TDelegate> removeHandler;
public FromEventObservable(Func<Action<TEventArgs>, TDelegate> conversion, Action<TDelegate> addHandler, Action<TDelegate> removeHandler)
: base(false)
{
this.conversion = conversion;
this.addHandler = addHandler;
this.removeHandler = removeHandler;
}
protected override IDisposable SubscribeCore(IObserver<TEventArgs> observer, IDisposable cancel)
{
var fe = new FromEvent(this, observer);
return fe.Register() ? fe : Disposable.Empty;
}
class FromEvent : IDisposable
{
readonly FromEventObservable<TDelegate, TEventArgs> parent;
readonly IObserver<TEventArgs> observer;
TDelegate handler;
public FromEvent(FromEventObservable<TDelegate, TEventArgs> parent, IObserver<TEventArgs> observer)
{
this.parent = parent;
this.observer = observer;
}
public bool Register()
{
handler = parent.conversion(OnNext);
try
{
parent.addHandler(handler);
}
catch (Exception ex)
{
observer.OnError(ex);
return false;
}
return true;
}
void OnNext(TEventArgs args)
{
observer.OnNext(args);
}
public void Dispose()
{
if (handler != null)
{
parent.removeHandler(handler);
handler = default(TDelegate);
}
}
}
}
internal class FromEventObservable : OperatorObservableBase<Unit>
{
readonly Action<Action> addHandler;
readonly Action<Action> removeHandler;
public FromEventObservable(Action<Action> addHandler, Action<Action> removeHandler)
: base(false)
{
this.addHandler = addHandler;
this.removeHandler = removeHandler;
}
protected override IDisposable SubscribeCore(IObserver<Unit> observer, IDisposable cancel)
{
var fe = new FromEvent(this, observer);
return fe.Register() ? fe : Disposable.Empty;
}
class FromEvent : IDisposable
{
readonly FromEventObservable parent;
readonly IObserver<Unit> observer;
Action handler;
public FromEvent(FromEventObservable parent, IObserver<Unit> observer)
{
this.parent = parent;
this.observer = observer;
this.handler = OnNext;
}
public bool Register()
{
try
{
parent.addHandler(handler);
}
catch (Exception ex)
{
observer.OnError(ex);
return false;
}
return true;
}
void OnNext()
{
observer.OnNext(Unit.Default);
}
public void Dispose()
{
if (handler != null)
{
parent.removeHandler(handler);
handler = null;
}
}
}
}
internal class FromEventObservable_<T> : OperatorObservableBase<T>
{
readonly Action<Action<T>> addHandler;
readonly Action<Action<T>> removeHandler;
public FromEventObservable_(Action<Action<T>> addHandler, Action<Action<T>> removeHandler)
: base(false)
{
this.addHandler = addHandler;
this.removeHandler = removeHandler;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
var fe = new FromEvent(this, observer);
return fe.Register() ? fe : Disposable.Empty;
}
class FromEvent : IDisposable
{
readonly FromEventObservable_<T> parent;
readonly IObserver<T> observer;
Action<T> handler;
public FromEvent(FromEventObservable_<T> parent, IObserver<T> observer)
{
this.parent = parent;
this.observer = observer;
this.handler = OnNext;
}
public bool Register()
{
try
{
parent.addHandler(handler);
}
catch (Exception ex)
{
observer.OnError(ex);
return false;
}
return true;
}
void OnNext(T value)
{
observer.OnNext(value);
}
public void Dispose()
{
if (handler != null)
{
parent.removeHandler(handler);
handler = null;
}
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 05fcc5083e94e704ca8f059e4e535ffa
timeCreated: 1455373897
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,196 @@
using System;
using System.Collections.Generic;
using UniRx.Operators;
namespace UniRx.Operators
{
internal class GroupedObservable<TKey, TElement> : IGroupedObservable<TKey, TElement>
{
readonly TKey key;
readonly IObservable<TElement> subject;
readonly RefCountDisposable refCount;
public TKey Key
{
get { return key; }
}
public GroupedObservable(TKey key, ISubject<TElement> subject, RefCountDisposable refCount)
{
this.key = key;
this.subject = subject;
this.refCount = refCount;
}
public IDisposable Subscribe(IObserver<TElement> observer)
{
var release = refCount.GetDisposable();
var subscription = subject.Subscribe(observer);
return StableCompositeDisposable.Create(release, subscription);
}
}
internal class GroupByObservable<TSource, TKey, TElement> : OperatorObservableBase<IGroupedObservable<TKey, TElement>>
{
readonly IObservable<TSource> source;
readonly Func<TSource, TKey> keySelector;
readonly Func<TSource, TElement> elementSelector;
readonly int? capacity;
readonly IEqualityComparer<TKey> comparer;
public GroupByObservable(IObservable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, int? capacity, IEqualityComparer<TKey> comparer)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.keySelector = keySelector;
this.elementSelector = elementSelector;
this.capacity = capacity;
this.comparer = comparer;
}
protected override IDisposable SubscribeCore(IObserver<IGroupedObservable<TKey, TElement>> observer, IDisposable cancel)
{
return new GroupBy(this, observer, cancel).Run();
}
class GroupBy : OperatorObserverBase<TSource, IGroupedObservable<TKey, TElement>>
{
readonly GroupByObservable<TSource, TKey, TElement> parent;
readonly Dictionary<TKey, ISubject<TElement>> map;
ISubject<TElement> nullKeySubject;
CompositeDisposable groupDisposable;
RefCountDisposable refCountDisposable;
public GroupBy(GroupByObservable<TSource, TKey, TElement> parent, IObserver<IGroupedObservable<TKey, TElement>> observer, IDisposable cancel)
: base(observer, cancel)
{
this.parent = parent;
if (parent.capacity.HasValue)
{
map = new Dictionary<TKey, ISubject<TElement>>(parent.capacity.Value, parent.comparer);
}
else
{
map = new Dictionary<TKey, ISubject<TElement>>(parent.comparer);
}
}
public IDisposable Run()
{
groupDisposable = new CompositeDisposable();
refCountDisposable = new RefCountDisposable(groupDisposable);
groupDisposable.Add(parent.source.Subscribe(this));
return refCountDisposable;
}
public override void OnNext(TSource value)
{
var key = default(TKey);
try
{
key = parent.keySelector(value);
}
catch (Exception exception)
{
Error(exception);
return;
}
var fireNewMapEntry = false;
var writer = default(ISubject<TElement>);
try
{
if (key == null)
{
if (nullKeySubject == null)
{
nullKeySubject = new Subject<TElement>();
fireNewMapEntry = true;
}
writer = nullKeySubject;
}
else
{
if (!map.TryGetValue(key, out writer))
{
writer = new Subject<TElement>();
map.Add(key, writer);
fireNewMapEntry = true;
}
}
}
catch (Exception exception)
{
Error(exception);
return;
}
if (fireNewMapEntry)
{
var group = new GroupedObservable<TKey, TElement>(key, writer, refCountDisposable);
observer.OnNext(group);
}
var element = default(TElement);
try
{
element = parent.elementSelector(value);
}
catch (Exception exception)
{
Error(exception);
return;
}
writer.OnNext(element);
}
public override void OnError(Exception error)
{
Error(error);
}
public override void OnCompleted()
{
try
{
if (nullKeySubject != null) nullKeySubject.OnCompleted();
foreach (var s in map.Values)
{
s.OnCompleted();
}
observer.OnCompleted();
}
finally
{
Dispose();
}
}
void Error(Exception exception)
{
try
{
if (nullKeySubject != null) nullKeySubject.OnError(exception);
foreach (var s in map.Values)
{
s.OnError(exception);
}
observer.OnError(exception);
}
finally
{
Dispose();
}
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 7345fc4a6df05ca47ab89ec819bccde6
timeCreated: 1455373899
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,44 @@
using System;
using UniRx.Operators;
namespace UniRx.Operators
{
internal class IgnoreElementsObservable<T> : OperatorObservableBase<T>
{
readonly IObservable<T> source;
public IgnoreElementsObservable(IObservable<T> source)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
return source.Subscribe(new IgnoreElements(observer, cancel));
}
class IgnoreElements : OperatorObserverBase<T, T>
{
public IgnoreElements(IObserver<T> observer, IDisposable cancel) : base(observer, cancel)
{
}
public override void OnNext(T value)
{
}
public override void OnError(Exception error)
{
try { observer.OnError(error); }
finally { Dispose(); }
}
public override void OnCompleted()
{
try { observer.OnCompleted(); }
finally { Dispose(); }
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: d6c8ca210619da74b92cbdb3e8c58127
timeCreated: 1455373901
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,165 @@
using System;
namespace UniRx.Operators
{
internal class LastObservable<T> : OperatorObservableBase<T>
{
readonly IObservable<T> source;
readonly bool useDefault;
readonly Func<T, bool> predicate;
public LastObservable(IObservable<T> source, bool useDefault)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.useDefault = useDefault;
}
public LastObservable(IObservable<T> source, Func<T, bool> predicate, bool useDefault)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.predicate = predicate;
this.useDefault = useDefault;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
if (predicate == null)
{
return source.Subscribe(new Last(this, observer, cancel));
}
else
{
return source.Subscribe(new Last_(this, observer, cancel));
}
}
class Last : OperatorObserverBase<T, T>
{
readonly LastObservable<T> parent;
bool notPublished;
T lastValue;
public Last(LastObservable<T> parent, IObserver<T> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
this.notPublished = true;
}
public override void OnNext(T value)
{
notPublished = false;
lastValue = value;
}
public override void OnError(Exception error)
{
try { observer.OnError(error); }
finally { Dispose(); }
}
public override void OnCompleted()
{
if (parent.useDefault)
{
if (notPublished)
{
observer.OnNext(default(T));
}
else
{
observer.OnNext(lastValue);
}
try { observer.OnCompleted(); }
finally { Dispose(); }
}
else
{
if (notPublished)
{
try { observer.OnError(new InvalidOperationException("sequence is empty")); }
finally { Dispose(); }
}
else
{
observer.OnNext(lastValue);
try { observer.OnCompleted(); }
finally { Dispose(); }
}
}
}
}
class Last_ : OperatorObserverBase<T, T>
{
readonly LastObservable<T> parent;
bool notPublished;
T lastValue;
public Last_(LastObservable<T> parent, IObserver<T> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
this.notPublished = true;
}
public override void OnNext(T value)
{
bool isPassed;
try
{
isPassed = parent.predicate(value);
}
catch (Exception ex)
{
try { observer.OnError(ex); }
finally { Dispose(); }
return;
}
if (isPassed)
{
notPublished = false;
lastValue = value;
}
}
public override void OnError(Exception error)
{
try { observer.OnError(error); }
finally { Dispose(); }
}
public override void OnCompleted()
{
if (parent.useDefault)
{
if (notPublished)
{
observer.OnNext(default(T));
}
else
{
observer.OnNext(lastValue);
}
try { observer.OnCompleted(); }
finally { Dispose(); }
}
else
{
if (notPublished)
{
try { observer.OnError(new InvalidOperationException("sequence is empty")); }
finally { Dispose(); }
}
else
{
observer.OnNext(lastValue);
try { observer.OnCompleted(); }
finally { Dispose(); }
}
}
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 696780c8759162d4b996683ec13d7e0b
timeCreated: 1455373899
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,53 @@
using System;
namespace UniRx.Operators
{
internal class MaterializeObservable<T> : OperatorObservableBase<Notification<T>>
{
readonly IObservable<T> source;
public MaterializeObservable(IObservable<T> source)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
}
protected override IDisposable SubscribeCore(IObserver<Notification<T>> observer, IDisposable cancel)
{
return new Materialize(this, observer, cancel).Run();
}
class Materialize : OperatorObserverBase<T, Notification<T>>
{
readonly MaterializeObservable<T> parent;
public Materialize(MaterializeObservable<T> parent, IObserver<Notification<T>> observer, IDisposable cancel)
: base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
return parent.source.Subscribe(this);
}
public override void OnNext(T value)
{
observer.OnNext(Notification.CreateOnNext(value));
}
public override void OnError(Exception error)
{
observer.OnNext(Notification.CreateOnError<T>(error));
try { observer.OnCompleted(); } finally { Dispose(); }
}
public override void OnCompleted()
{
observer.OnNext(Notification.CreateOnCompleted<T>());
try { observer.OnCompleted(); } finally { Dispose(); }
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 09d3ba9e6d5fe4643bbf0df943652908
timeCreated: 1455373897
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,264 @@
using System;
using System.Collections.Generic;
namespace UniRx.Operators
{
internal class MergeObservable<T> : OperatorObservableBase<T>
{
private readonly IObservable<IObservable<T>> sources;
private readonly int maxConcurrent;
public MergeObservable(IObservable<IObservable<T>> sources, bool isRequiredSubscribeOnCurrentThread)
: base(isRequiredSubscribeOnCurrentThread)
{
this.sources = sources;
}
public MergeObservable(IObservable<IObservable<T>> sources, int maxConcurrent, bool isRequiredSubscribeOnCurrentThread)
: base(isRequiredSubscribeOnCurrentThread)
{
this.sources = sources;
this.maxConcurrent = maxConcurrent;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
if (maxConcurrent > 0)
{
return new MergeConcurrentObserver(this, observer, cancel).Run();
}
else
{
return new MergeOuterObserver(this, observer, cancel).Run();
}
}
class MergeOuterObserver : OperatorObserverBase<IObservable<T>, T>
{
readonly MergeObservable<T> parent;
CompositeDisposable collectionDisposable;
SingleAssignmentDisposable sourceDisposable;
object gate = new object();
bool isStopped = false;
public MergeOuterObserver(MergeObservable<T> parent, IObserver<T> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
collectionDisposable = new CompositeDisposable();
sourceDisposable = new SingleAssignmentDisposable();
collectionDisposable.Add(sourceDisposable);
sourceDisposable.Disposable = parent.sources.Subscribe(this);
return collectionDisposable;
}
public override void OnNext(IObservable<T> value)
{
var disposable = new SingleAssignmentDisposable();
collectionDisposable.Add(disposable);
var collectionObserver = new Merge(this, disposable);
disposable.Disposable = value.Subscribe(collectionObserver);
}
public override void OnError(Exception error)
{
lock (gate)
{
try { observer.OnError(error); } finally { Dispose(); };
}
}
public override void OnCompleted()
{
isStopped = true;
if (collectionDisposable.Count == 1)
{
lock (gate)
{
try { observer.OnCompleted(); } finally { Dispose(); };
}
}
else
{
sourceDisposable.Dispose();
}
}
class Merge : OperatorObserverBase<T, T>
{
readonly MergeOuterObserver parent;
readonly IDisposable cancel;
public Merge(MergeOuterObserver parent, IDisposable cancel)
: base(parent.observer, cancel)
{
this.parent = parent;
this.cancel = cancel;
}
public override void OnNext(T value)
{
lock (parent.gate)
{
base.observer.OnNext(value);
}
}
public override void OnError(Exception error)
{
lock (parent.gate)
{
try { observer.OnError(error); } finally { Dispose(); };
}
}
public override void OnCompleted()
{
parent.collectionDisposable.Remove(cancel);
if (parent.isStopped && parent.collectionDisposable.Count == 1)
{
lock (parent.gate)
{
try { observer.OnCompleted(); } finally { Dispose(); };
}
}
}
}
}
class MergeConcurrentObserver : OperatorObserverBase<IObservable<T>, T>
{
readonly MergeObservable<T> parent;
CompositeDisposable collectionDisposable;
SingleAssignmentDisposable sourceDisposable;
object gate = new object();
bool isStopped = false;
// concurrency
Queue<IObservable<T>> q;
int activeCount;
public MergeConcurrentObserver(MergeObservable<T> parent, IObserver<T> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
q = new Queue<IObservable<T>>();
activeCount = 0;
collectionDisposable = new CompositeDisposable();
sourceDisposable = new SingleAssignmentDisposable();
collectionDisposable.Add(sourceDisposable);
sourceDisposable.Disposable = parent.sources.Subscribe(this);
return collectionDisposable;
}
public override void OnNext(IObservable<T> value)
{
lock (gate)
{
if (activeCount < parent.maxConcurrent)
{
activeCount++;
Subscribe(value);
}
else
{
q.Enqueue(value);
}
}
}
public override void OnError(Exception error)
{
lock (gate)
{
try { observer.OnError(error); } finally { Dispose(); };
}
}
public override void OnCompleted()
{
lock (gate)
{
isStopped = true;
if (activeCount == 0)
{
try { observer.OnCompleted(); } finally { Dispose(); };
}
else
{
sourceDisposable.Dispose();
}
}
}
void Subscribe(IObservable<T> innerSource)
{
var disposable = new SingleAssignmentDisposable();
collectionDisposable.Add(disposable);
var collectionObserver = new Merge(this, disposable);
disposable.Disposable = innerSource.Subscribe(collectionObserver);
}
class Merge : OperatorObserverBase<T, T>
{
readonly MergeConcurrentObserver parent;
readonly IDisposable cancel;
public Merge(MergeConcurrentObserver parent, IDisposable cancel)
: base(parent.observer, cancel)
{
this.parent = parent;
this.cancel = cancel;
}
public override void OnNext(T value)
{
lock (parent.gate)
{
base.observer.OnNext(value);
}
}
public override void OnError(Exception error)
{
lock (parent.gate)
{
try { observer.OnError(error); } finally { Dispose(); };
}
}
public override void OnCompleted()
{
parent.collectionDisposable.Remove(cancel);
lock (parent.gate)
{
if (parent.q.Count > 0)
{
var source = parent.q.Dequeue();
parent.Subscribe(source);
}
else
{
parent.activeCount--;
if (parent.isStopped && parent.activeCount == 0)
{
try { observer.OnCompleted(); } finally { Dispose(); };
}
}
}
}
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 94158fab525468d4e896a62f633257e6
timeCreated: 1455373900
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,32 @@
using System;
namespace UniRx.Operators
{
internal class NeverObservable<T> : OperatorObservableBase<T>
{
public NeverObservable()
: base(false)
{
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
return Disposable.Empty;
}
}
internal class ImmutableNeverObservable<T> : IObservable<T>, IOptimizedObservable<T>
{
internal static ImmutableNeverObservable<T> Instance = new ImmutableNeverObservable<T>();
public bool IsRequiredSubscribeOnCurrentThread()
{
return false;
}
public IDisposable Subscribe(IObserver<T> observer)
{
return Disposable.Empty;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: b5db8d5c73883214abaf3715002da256
timeCreated: 1455373900
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,210 @@
using System;
using System.Collections.Generic;
namespace UniRx.Operators
{
internal class ObserveOnObservable<T> : OperatorObservableBase<T>
{
readonly IObservable<T> source;
readonly IScheduler scheduler;
public ObserveOnObservable(IObservable<T> source, IScheduler scheduler)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.scheduler = scheduler;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
var queueing = scheduler as ISchedulerQueueing;
if (queueing == null)
{
return new ObserveOn(this, observer, cancel).Run();
}
else
{
return new ObserveOn_(this, queueing, observer, cancel).Run();
}
}
class ObserveOn : OperatorObserverBase<T, T>
{
class SchedulableAction : IDisposable
{
public Notification<T> data;
public LinkedListNode<SchedulableAction> node;
public IDisposable schedule;
public void Dispose()
{
if (schedule != null)
schedule.Dispose();
schedule = null;
if (node.List != null)
{
node.List.Remove(node);
}
}
public bool IsScheduled { get { return schedule != null; } }
}
readonly ObserveOnObservable<T> parent;
readonly LinkedList<SchedulableAction> actions = new LinkedList<SchedulableAction>();
bool isDisposed;
public ObserveOn(ObserveOnObservable<T> parent, IObserver<T> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
isDisposed = false;
var sourceDisposable = parent.source.Subscribe(this);
return StableCompositeDisposable.Create(sourceDisposable, Disposable.Create(() =>
{
lock (actions)
{
isDisposed = true;
while (actions.Count > 0)
{
// Dispose will both cancel the action (if not already running)
// and remove it from 'actions'
actions.First.Value.Dispose();
}
}
}));
}
public override void OnNext(T value)
{
QueueAction(new Notification<T>.OnNextNotification(value));
}
public override void OnError(Exception error)
{
QueueAction(new Notification<T>.OnErrorNotification(error));
}
public override void OnCompleted()
{
QueueAction(new Notification<T>.OnCompletedNotification());
}
private void QueueAction(Notification<T> data)
{
var action = new SchedulableAction { data = data };
lock (actions)
{
if (isDisposed) return;
action.node = actions.AddLast(action);
ProcessNext();
}
}
private void ProcessNext()
{
lock (actions)
{
if (actions.Count == 0 || isDisposed)
return;
var action = actions.First.Value;
if (action.IsScheduled)
return;
action.schedule = parent.scheduler.Schedule(() =>
{
try
{
switch (action.data.Kind)
{
case NotificationKind.OnNext:
observer.OnNext(action.data.Value);
break;
case NotificationKind.OnError:
observer.OnError(action.data.Exception);
break;
case NotificationKind.OnCompleted:
observer.OnCompleted();
break;
}
}
finally
{
lock (actions)
{
action.Dispose();
}
if (action.data.Kind == NotificationKind.OnNext)
ProcessNext();
else
Dispose();
}
});
}
}
}
class ObserveOn_ : OperatorObserverBase<T, T>
{
readonly ObserveOnObservable<T> parent;
readonly ISchedulerQueueing scheduler;
readonly BooleanDisposable isDisposed;
readonly Action<T> onNext;
public ObserveOn_(ObserveOnObservable<T> parent, ISchedulerQueueing scheduler, IObserver<T> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
this.scheduler = scheduler;
this.isDisposed = new BooleanDisposable();
this.onNext = new Action<T>(OnNext_); // cache delegate
}
public IDisposable Run()
{
var sourceDisposable = parent.source.Subscribe(this);
return StableCompositeDisposable.Create(sourceDisposable, isDisposed);
}
void OnNext_(T value)
{
base.observer.OnNext(value);
}
void OnError_(Exception error)
{
try { observer.OnError(error); } finally { Dispose(); };
}
void OnCompleted_(Unit _)
{
try { observer.OnCompleted(); } finally { Dispose(); };
}
public override void OnNext(T value)
{
scheduler.ScheduleQueueing(isDisposed, value, onNext);
}
public override void OnError(Exception error)
{
scheduler.ScheduleQueueing(isDisposed, error, OnError_);
}
public override void OnCompleted()
{
scheduler.ScheduleQueueing(isDisposed, Unit.Default, OnCompleted_);
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 39df784f492c7404286d05b09a840705
timeCreated: 1455373898
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,47 @@
using System;
namespace UniRx.Operators
{
internal class OfTypeObservable<TSource, TResult> : OperatorObservableBase<TResult>
{
readonly IObservable<TSource> source;
public OfTypeObservable(IObservable<TSource> source)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
}
protected override IDisposable SubscribeCore(IObserver<TResult> observer, IDisposable cancel)
{
return source.Subscribe(new OfType(observer, cancel));
}
class OfType : OperatorObserverBase<TSource, TResult>
{
public OfType(IObserver<TResult> observer, IDisposable cancel)
: base(observer, cancel)
{
}
public override void OnNext(TSource value)
{
if (value is TResult)
{
var castValue = (TResult)(object)value;
observer.OnNext(castValue);
}
}
public override void OnError(Exception error)
{
try { observer.OnError(error); } finally { Dispose(); }
}
public override void OnCompleted()
{
try { observer.OnCompleted(); } finally { Dispose(); }
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 981fd4bf7704404459a0deed254a03e5
timeCreated: 1455373900
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,42 @@
using System;
namespace UniRx.Operators
{
// implements note : all field must be readonly.
public abstract class OperatorObservableBase<T> : IObservable<T>, IOptimizedObservable<T>
{
readonly bool isRequiredSubscribeOnCurrentThread;
public OperatorObservableBase(bool isRequiredSubscribeOnCurrentThread)
{
this.isRequiredSubscribeOnCurrentThread = isRequiredSubscribeOnCurrentThread;
}
public bool IsRequiredSubscribeOnCurrentThread()
{
return isRequiredSubscribeOnCurrentThread;
}
public IDisposable Subscribe(IObserver<T> observer)
{
var subscription = new SingleAssignmentDisposable();
// note:
// does not make the safe observer, it breaks exception durability.
// var safeObserver = Observer.CreateAutoDetachObserver<T>(observer, subscription);
if (isRequiredSubscribeOnCurrentThread && Scheduler.IsCurrentThreadSchedulerScheduleRequired)
{
Scheduler.CurrentThread.Schedule(() => subscription.Disposable = SubscribeCore(observer, subscription));
}
else
{
subscription.Disposable = SubscribeCore(observer, subscription);
}
return subscription;
}
protected abstract IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel);
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 1b94a1a0ae5d509488c6242454216bdb
timeCreated: 1455373897
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,33 @@
using System;
using System.Threading;
namespace UniRx.Operators
{
public abstract class OperatorObserverBase<TSource, TResult> : IDisposable, IObserver<TSource>
{
protected internal volatile IObserver<TResult> observer;
IDisposable cancel;
public OperatorObserverBase(IObserver<TResult> observer, IDisposable cancel)
{
this.observer = observer;
this.cancel = cancel;
}
public abstract void OnNext(TSource value);
public abstract void OnError(Exception error);
public abstract void OnCompleted();
public void Dispose()
{
observer = UniRx.InternalUtil.EmptyObserver<TResult>.Instance;
var target = System.Threading.Interlocked.Exchange(ref cancel, null);
if (target != null)
{
target.Dispose();
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 258901a4513be8f4a8bfcca91e70bb12
timeCreated: 1455373898
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,120 @@
using System;
namespace UniRx.Operators
{
internal class PairwiseObservable<T, TR> : OperatorObservableBase<TR>
{
readonly IObservable<T> source;
readonly Func<T, T, TR> selector;
public PairwiseObservable(IObservable<T> source, Func<T, T, TR> selector)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.selector = selector;
}
protected override IDisposable SubscribeCore(IObserver<TR> observer, IDisposable cancel)
{
return source.Subscribe(new Pairwise(this, observer, cancel));
}
class Pairwise : OperatorObserverBase<T, TR>
{
readonly PairwiseObservable<T, TR> parent;
T prev = default(T);
bool isFirst = true;
public Pairwise(PairwiseObservable<T, TR> parent, IObserver<TR> observer, IDisposable cancel)
: base(observer, cancel)
{
this.parent = parent;
}
public override void OnNext(T value)
{
if (isFirst)
{
isFirst = false;
prev = value;
return;
}
TR v;
try
{
v = parent.selector(prev, value);
prev = value;
}
catch (Exception ex)
{
try { observer.OnError(ex); } finally { Dispose(); }
return;
}
observer.OnNext(v);
}
public override void OnError(Exception error)
{
try { observer.OnError(error); } finally { Dispose(); }
}
public override void OnCompleted()
{
try { observer.OnCompleted(); } finally { Dispose(); }
}
}
}
internal class PairwiseObservable<T> : OperatorObservableBase<Pair<T>>
{
readonly IObservable<T> source;
public PairwiseObservable(IObservable<T> source)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
}
protected override IDisposable SubscribeCore(IObserver<Pair<T>> observer, IDisposable cancel)
{
return source.Subscribe(new Pairwise(observer, cancel));
}
class Pairwise : OperatorObserverBase<T, Pair<T>>
{
T prev = default(T);
bool isFirst = true;
public Pairwise(IObserver<Pair<T>> observer, IDisposable cancel)
: base(observer, cancel)
{
}
public override void OnNext(T value)
{
if (isFirst)
{
isFirst = false;
prev = value;
return;
}
var pair = new Pair<T>(prev, value);
prev = value;
observer.OnNext(pair);
}
public override void OnError(Exception error)
{
try { observer.OnError(error); } finally { Dispose(); }
}
public override void OnCompleted()
{
try { observer.OnCompleted(); } finally { Dispose(); }
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: f66e4871304e6e74d8548d597457e53c
timeCreated: 1455373902
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,89 @@
using System;
namespace UniRx.Operators
{
internal class RangeObservable : OperatorObservableBase<int>
{
readonly int start;
readonly int count;
readonly IScheduler scheduler;
public RangeObservable(int start, int count, IScheduler scheduler)
: base(scheduler == Scheduler.CurrentThread)
{
if (count < 0) throw new ArgumentOutOfRangeException("count < 0");
this.start = start;
this.count = count;
this.scheduler = scheduler;
}
protected override IDisposable SubscribeCore(IObserver<int> observer, IDisposable cancel)
{
observer = new Range(observer, cancel);
if (scheduler == Scheduler.Immediate)
{
for (int i = 0; i < count; i++)
{
int v = start + i;
observer.OnNext(v);
}
observer.OnCompleted();
return Disposable.Empty;
}
else
{
var i = 0;
return scheduler.Schedule((Action self) =>
{
if (i < count)
{
int v = start + i;
observer.OnNext(v);
i++;
self();
}
else
{
observer.OnCompleted();
}
});
}
}
class Range : OperatorObserverBase<int, int>
{
public Range(IObserver<int> observer, IDisposable cancel)
: base(observer, cancel)
{
}
public override void OnNext(int value)
{
try
{
base.observer.OnNext(value);
}
catch
{
Dispose();
throw;
}
}
public override void OnError(Exception error)
{
try { observer.OnError(error); }
finally { Dispose(); }
}
public override void OnCompleted()
{
try { observer.OnCompleted(); }
finally { Dispose(); }
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 2249fbe589c8d3042ac201c1ab4be76f
timeCreated: 1455373897
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,77 @@
using System;
using UniRx.Operators;
namespace UniRx.Operators
{
internal class RefCountObservable<T> : OperatorObservableBase<T>
{
readonly IConnectableObservable<T> source;
readonly object gate = new object();
int refCount = 0;
IDisposable connection;
public RefCountObservable(IConnectableObservable<T> source)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
return new RefCount(this, observer, cancel).Run();
}
class RefCount : OperatorObserverBase<T, T>
{
readonly RefCountObservable<T> parent;
public RefCount(RefCountObservable<T> parent, IObserver<T> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
var subcription = parent.source.Subscribe(this);
lock (parent.gate)
{
if (++parent.refCount == 1)
{
parent.connection = parent.source.Connect();
}
}
return Disposable.Create(() =>
{
subcription.Dispose();
lock (parent.gate)
{
if (--parent.refCount == 0)
{
parent.connection.Dispose();
}
}
});
}
public override void OnNext(T value)
{
base.observer.OnNext(value);
}
public override void OnError(Exception error)
{
try { observer.OnError(error); }
finally { Dispose(); }
}
public override void OnCompleted()
{
try { observer.OnCompleted(); }
finally { Dispose(); }
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 17a77b422aa699d4d8cfbf6de804d238
timeCreated: 1455373897
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,99 @@
using System;
namespace UniRx.Operators
{
internal class RepeatObservable<T> : OperatorObservableBase<T>
{
readonly T value;
readonly int? repeatCount;
readonly IScheduler scheduler;
public RepeatObservable(T value, int? repeatCount, IScheduler scheduler)
: base(scheduler == Scheduler.CurrentThread)
{
this.value = value;
this.repeatCount = repeatCount;
this.scheduler = scheduler;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
observer = new Repeat(observer, cancel);
if (repeatCount == null)
{
return scheduler.Schedule((Action self) =>
{
observer.OnNext(value);
self();
});
}
else
{
if (scheduler == Scheduler.Immediate)
{
var count = this.repeatCount.Value;
for (int i = 0; i < count; i++)
{
observer.OnNext(value);
}
observer.OnCompleted();
return Disposable.Empty;
}
else
{
var currentCount = this.repeatCount.Value;
return scheduler.Schedule((Action self) =>
{
if (currentCount > 0)
{
observer.OnNext(value);
currentCount--;
}
if (currentCount == 0)
{
observer.OnCompleted();
return;
}
self();
});
}
}
}
class Repeat : OperatorObserverBase<T, T>
{
public Repeat(IObserver<T> observer, IDisposable cancel)
: base(observer, cancel)
{
}
public override void OnNext(T value)
{
try
{
base.observer.OnNext(value);
}
catch
{
Dispose();
throw;
}
}
public override void OnError(Exception error)
{
try { observer.OnError(error); }
finally { Dispose(); }
}
public override void OnCompleted()
{
try { observer.OnCompleted(); }
finally { Dispose(); }
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 63930706f2ea6e847866fc6d914b0d2e
timeCreated: 1455373899
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,138 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace UniRx.Operators
{
internal class RepeatSafeObservable<T> : OperatorObservableBase<T>
{
readonly IEnumerable<IObservable<T>> sources;
public RepeatSafeObservable(IEnumerable<IObservable<T>> sources, bool isRequiredSubscribeOnCurrentThread)
: base(isRequiredSubscribeOnCurrentThread)
{
this.sources = sources;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
return new RepeatSafe(this, observer, cancel).Run();
}
class RepeatSafe : OperatorObserverBase<T, T>
{
readonly RepeatSafeObservable<T> parent;
readonly object gate = new object();
IEnumerator<IObservable<T>> e;
SerialDisposable subscription;
Action nextSelf;
bool isDisposed;
bool isRunNext;
public RepeatSafe(RepeatSafeObservable<T> parent, IObserver<T> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
isDisposed = false;
isRunNext = false;
e = parent.sources.GetEnumerator();
subscription = new SerialDisposable();
var schedule = Scheduler.DefaultSchedulers.TailRecursion.Schedule(RecursiveRun);
return StableCompositeDisposable.Create(schedule, subscription, Disposable.Create(() =>
{
lock (gate)
{
isDisposed = true;
e.Dispose();
}
}));
}
void RecursiveRun(Action self)
{
lock (gate)
{
this.nextSelf = self;
if (isDisposed) return;
var current = default(IObservable<T>);
var hasNext = false;
var ex = default(Exception);
try
{
hasNext = e.MoveNext();
if (hasNext)
{
current = e.Current;
if (current == null) throw new InvalidOperationException("sequence is null.");
}
else
{
e.Dispose();
}
}
catch (Exception exception)
{
ex = exception;
e.Dispose();
}
if (ex != null)
{
try { observer.OnError(ex); }
finally { Dispose(); }
return;
}
if (!hasNext)
{
try { observer.OnCompleted(); }
finally { Dispose(); }
return;
}
var source = e.Current;
var d = new SingleAssignmentDisposable();
subscription.Disposable = d;
d.Disposable = source.Subscribe(this);
}
}
public override void OnNext(T value)
{
isRunNext = true;
base.observer.OnNext(value);
}
public override void OnError(Exception error)
{
try { observer.OnError(error); }
finally { Dispose(); }
}
public override void OnCompleted()
{
if (isRunNext && !isDisposed)
{
isRunNext = false;
this.nextSelf();
}
else
{
e.Dispose();
if (!isDisposed)
{
try { observer.OnCompleted(); }
finally { Dispose(); }
}
}
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 6458fa5124443dc4bb95ad3d0b743934
timeCreated: 1455373899
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,205 @@
using System;
namespace UniRx.Operators
{
internal class ReturnObservable<T> : OperatorObservableBase<T>
{
readonly T value;
readonly IScheduler scheduler;
public ReturnObservable(T value, IScheduler scheduler)
: base(scheduler == Scheduler.CurrentThread)
{
this.value = value;
this.scheduler = scheduler;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
observer = new Return(observer, cancel);
if (scheduler == Scheduler.Immediate)
{
observer.OnNext(value);
observer.OnCompleted();
return Disposable.Empty;
}
else
{
return scheduler.Schedule(() =>
{
observer.OnNext(value);
observer.OnCompleted();
});
}
}
class Return : OperatorObserverBase<T, T>
{
public Return(IObserver<T> observer, IDisposable cancel)
: base(observer, cancel)
{
}
public override void OnNext(T value)
{
try
{
base.observer.OnNext(value);
}
catch
{
Dispose();
throw;
}
}
public override void OnError(Exception error)
{
try { observer.OnError(error); }
finally { Dispose(); }
}
public override void OnCompleted()
{
try { observer.OnCompleted(); }
finally { Dispose(); }
}
}
}
internal class ImmediateReturnObservable<T> : IObservable<T>, IOptimizedObservable<T>
{
readonly T value;
public ImmediateReturnObservable(T value)
{
this.value = value;
}
public bool IsRequiredSubscribeOnCurrentThread()
{
return false;
}
public IDisposable Subscribe(IObserver<T> observer)
{
observer.OnNext(value);
observer.OnCompleted();
return Disposable.Empty;
}
}
internal class ImmutableReturnUnitObservable : IObservable<Unit>, IOptimizedObservable<Unit>
{
internal static ImmutableReturnUnitObservable Instance = new ImmutableReturnUnitObservable();
ImmutableReturnUnitObservable()
{
}
public bool IsRequiredSubscribeOnCurrentThread()
{
return false;
}
public IDisposable Subscribe(IObserver<Unit> observer)
{
observer.OnNext(Unit.Default);
observer.OnCompleted();
return Disposable.Empty;
}
}
internal class ImmutableReturnTrueObservable : IObservable<bool>, IOptimizedObservable<bool>
{
internal static ImmutableReturnTrueObservable Instance = new ImmutableReturnTrueObservable();
ImmutableReturnTrueObservable()
{
}
public bool IsRequiredSubscribeOnCurrentThread()
{
return false;
}
public IDisposable Subscribe(IObserver<bool> observer)
{
observer.OnNext(true);
observer.OnCompleted();
return Disposable.Empty;
}
}
internal class ImmutableReturnFalseObservable : IObservable<bool>, IOptimizedObservable<bool>
{
internal static ImmutableReturnFalseObservable Instance = new ImmutableReturnFalseObservable();
ImmutableReturnFalseObservable()
{
}
public bool IsRequiredSubscribeOnCurrentThread()
{
return false;
}
public IDisposable Subscribe(IObserver<bool> observer)
{
observer.OnNext(false);
observer.OnCompleted();
return Disposable.Empty;
}
}
internal class ImmutableReturnInt32Observable : IObservable<int>, IOptimizedObservable<int>
{
static ImmutableReturnInt32Observable[] Caches = new ImmutableReturnInt32Observable[]
{
new ImmutableReturnInt32Observable(-1),
new ImmutableReturnInt32Observable(0),
new ImmutableReturnInt32Observable(1),
new ImmutableReturnInt32Observable(2),
new ImmutableReturnInt32Observable(3),
new ImmutableReturnInt32Observable(4),
new ImmutableReturnInt32Observable(5),
new ImmutableReturnInt32Observable(6),
new ImmutableReturnInt32Observable(7),
new ImmutableReturnInt32Observable(8),
new ImmutableReturnInt32Observable(9),
};
public static IObservable<int> GetInt32Observable(int x)
{
if (-1 <= x && x <= 9)
{
return Caches[x + 1];
}
return new ImmediateReturnObservable<int>(x);
}
readonly int x;
ImmutableReturnInt32Observable(int x)
{
this.x = x;
}
public bool IsRequiredSubscribeOnCurrentThread()
{
return false;
}
public IDisposable Subscribe(IObserver<int> observer)
{
observer.OnNext(x);
observer.OnCompleted();
return Disposable.Empty;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 25648117feeec6043bd39468bfab62b7
timeCreated: 1455373898
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,241 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UniRx.Operators
{
internal class SampleObservable<T> : OperatorObservableBase<T>
{
readonly IObservable<T> source;
readonly TimeSpan interval;
readonly IScheduler scheduler;
public SampleObservable(IObservable<T> source, TimeSpan interval, IScheduler scheduler)
: base(source.IsRequiredSubscribeOnCurrentThread() || scheduler == Scheduler.CurrentThread)
{
this.source = source;
this.interval = interval;
this.scheduler = scheduler;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
return new Sample(this, observer, cancel).Run();
}
class Sample : OperatorObserverBase<T, T>
{
readonly SampleObservable<T> parent;
readonly object gate = new object();
T latestValue = default(T);
bool isUpdated = false;
bool isCompleted = false;
SingleAssignmentDisposable sourceSubscription;
public Sample(SampleObservable<T> parent, IObserver<T> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
sourceSubscription = new SingleAssignmentDisposable();
sourceSubscription.Disposable = parent.source.Subscribe(this);
IDisposable scheduling;
var periodicScheduler = parent.scheduler as ISchedulerPeriodic;
if (periodicScheduler != null)
{
scheduling = periodicScheduler.SchedulePeriodic(parent.interval, OnNextTick);
}
else
{
scheduling = parent.scheduler.Schedule(parent.interval, OnNextRecursive);
}
return StableCompositeDisposable.Create(sourceSubscription, scheduling);
}
void OnNextTick()
{
lock (gate)
{
if (isUpdated)
{
var value = latestValue;
isUpdated = false;
observer.OnNext(value);
}
if (isCompleted)
{
try { observer.OnCompleted(); } finally { Dispose(); }
}
}
}
void OnNextRecursive(Action<TimeSpan> self)
{
lock (gate)
{
if (isUpdated)
{
var value = latestValue;
isUpdated = false;
observer.OnNext(value);
}
if (isCompleted)
{
try { observer.OnCompleted(); } finally { Dispose(); }
}
}
self(parent.interval);
}
public override void OnNext(T value)
{
lock (gate)
{
latestValue = value;
isUpdated = true;
}
}
public override void OnError(Exception error)
{
lock (gate)
{
try { base.observer.OnError(error); } finally { Dispose(); }
}
}
public override void OnCompleted()
{
lock (gate)
{
isCompleted = true;
sourceSubscription.Dispose();
}
}
}
}
internal class SampleObservable<T, T2> : OperatorObservableBase<T>
{
readonly IObservable<T> source;
readonly IObservable<T2> intervalSource;
public SampleObservable(IObservable<T> source, IObservable<T2> intervalSource)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.intervalSource = intervalSource;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
return new Sample(this, observer, cancel).Run();
}
class Sample : OperatorObserverBase<T, T>
{
readonly SampleObservable<T, T2> parent;
readonly object gate = new object();
T latestValue = default(T);
bool isUpdated = false;
bool isCompleted = false;
SingleAssignmentDisposable sourceSubscription;
public Sample(
SampleObservable<T, T2> parent, IObserver<T> observer, IDisposable cancel)
: base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
sourceSubscription = new SingleAssignmentDisposable();
sourceSubscription.Disposable = parent.source.Subscribe(this);
var scheduling = this.parent.intervalSource.Subscribe(new SampleTick(this));
return StableCompositeDisposable.Create(sourceSubscription, scheduling);
}
public override void OnNext(T value)
{
lock (gate)
{
latestValue = value;
isUpdated = true;
}
}
public override void OnError(Exception error)
{
lock (gate)
{
try { base.observer.OnError(error); } finally { Dispose(); }
}
}
public override void OnCompleted()
{
lock (gate)
{
isCompleted = true;
sourceSubscription.Dispose();
}
}
class SampleTick : IObserver<T2>
{
readonly Sample parent;
public SampleTick(Sample parent)
{
this.parent = parent;
}
public void OnCompleted()
{
lock (parent.gate)
{
if (parent.isUpdated)
{
parent.isUpdated = false;
parent.observer.OnNext(parent.latestValue);
}
if (parent.isCompleted)
{
try { parent.observer.OnCompleted(); } finally { parent.Dispose(); }
}
}
}
public void OnError(Exception error)
{
}
public void OnNext(T2 _)
{
lock (parent.gate)
{
if (parent.isUpdated)
{
var value = parent.latestValue;
parent.isUpdated = false;
parent.observer.OnNext(value);
}
if (parent.isCompleted)
{
try { parent.observer.OnCompleted(); } finally { parent.Dispose(); }
}
}
}
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 414e918f6a4dfc549b2a8c916a6325e1
timeCreated: 1455373898
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,139 @@
using System;
using UniRx.Operators;
namespace UniRx.Operators
{
internal class ScanObservable<TSource> : OperatorObservableBase<TSource>
{
readonly IObservable<TSource> source;
readonly Func<TSource, TSource, TSource> accumulator;
public ScanObservable(IObservable<TSource> source, Func<TSource, TSource, TSource> accumulator)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.accumulator = accumulator;
}
protected override IDisposable SubscribeCore(IObserver<TSource> observer, IDisposable cancel)
{
return source.Subscribe(new Scan(this, observer, cancel));
}
class Scan : OperatorObserverBase<TSource, TSource>
{
readonly ScanObservable<TSource> parent;
TSource accumulation;
bool isFirst;
public Scan(ScanObservable<TSource> parent, IObserver<TSource> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
this.isFirst = true;
}
public override void OnNext(TSource value)
{
if (isFirst)
{
isFirst = false;
accumulation = value;
}
else
{
try
{
accumulation = parent.accumulator(accumulation, value);
}
catch (Exception ex)
{
try { observer.OnError(ex); }
finally { Dispose(); }
return;
}
}
observer.OnNext(accumulation);
}
public override void OnError(Exception error)
{
try { observer.OnError(error); }
finally { Dispose(); }
}
public override void OnCompleted()
{
try { observer.OnCompleted(); }
finally { Dispose(); }
}
}
}
internal class ScanObservable<TSource, TAccumulate> : OperatorObservableBase<TAccumulate>
{
readonly IObservable<TSource> source;
readonly TAccumulate seed;
readonly Func<TAccumulate, TSource, TAccumulate> accumulator;
public ScanObservable(IObservable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.seed = seed;
this.accumulator = accumulator;
}
protected override IDisposable SubscribeCore(IObserver<TAccumulate> observer, IDisposable cancel)
{
return source.Subscribe(new Scan(this, observer, cancel));
}
class Scan : OperatorObserverBase<TSource, TAccumulate>
{
readonly ScanObservable<TSource, TAccumulate> parent;
TAccumulate accumulation;
bool isFirst;
public Scan(ScanObservable<TSource, TAccumulate> parent, IObserver<TAccumulate> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
this.isFirst = true;
}
public override void OnNext(TSource value)
{
if (isFirst)
{
isFirst = false;
accumulation = parent.seed;
}
try
{
accumulation = parent.accumulator(accumulation, value);
}
catch (Exception ex)
{
try { observer.OnError(ex); }
finally { Dispose(); }
return;
}
observer.OnNext(accumulation);
}
public override void OnError(Exception error)
{
try { observer.OnError(error); }
finally { Dispose(); }
}
public override void OnCompleted()
{
try { observer.OnCompleted(); }
finally { Dispose(); }
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 461fecd0ef4d48c4d95aae68c2ca2c1c
timeCreated: 1455373898
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,146 @@
using System;
namespace UniRx.Operators
{
internal interface ISelect<TR>
{
// IObservable<TR2> CombineSelector<TR2>(Func<TR, TR2> selector);
IObservable<TR> CombinePredicate(Func<TR, bool> predicate);
}
internal class SelectObservable<T, TR> : OperatorObservableBase<TR>, ISelect<TR>
{
readonly IObservable<T> source;
readonly Func<T, TR> selector;
readonly Func<T, int, TR> selectorWithIndex;
public SelectObservable(IObservable<T> source, Func<T, TR> selector)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.selector = selector;
}
public SelectObservable(IObservable<T> source, Func<T, int, TR> selector)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.selectorWithIndex = selector;
}
// sometimes cause "which no ahead of time (AOT) code was generated." on IL2CPP...
//public IObservable<TR2> CombineSelector<TR2>(Func<TR, TR2> combineSelector)
//{
// if (this.selector != null)
// {
// return new Select<T, TR2>(source, x => combineSelector(this.selector(x)));
// }
// else
// {
// return new Select<TR, TR2>(this, combineSelector);
// }
//}
public IObservable<TR> CombinePredicate(Func<TR, bool> predicate)
{
if (this.selector != null)
{
return new SelectWhereObservable<T, TR>(this.source, this.selector, predicate);
}
else
{
return new WhereObservable<TR>(this, predicate); // can't combine
}
}
protected override IDisposable SubscribeCore(IObserver<TR> observer, IDisposable cancel)
{
if (selector != null)
{
return source.Subscribe(new Select(this, observer, cancel));
}
else
{
return source.Subscribe(new Select_(this, observer, cancel));
}
}
class Select : OperatorObserverBase<T, TR>
{
readonly SelectObservable<T, TR> parent;
public Select(SelectObservable<T, TR> parent, IObserver<TR> observer, IDisposable cancel)
: base(observer, cancel)
{
this.parent = parent;
}
public override void OnNext(T value)
{
var v = default(TR);
try
{
v = parent.selector(value);
}
catch (Exception ex)
{
try { observer.OnError(ex); } finally { Dispose(); }
return;
}
observer.OnNext(v);
}
public override void OnError(Exception error)
{
try { observer.OnError(error); } finally { Dispose(); }
}
public override void OnCompleted()
{
try { observer.OnCompleted(); } finally { Dispose(); }
}
}
// with Index
class Select_ : OperatorObserverBase<T, TR>
{
readonly SelectObservable<T, TR> parent;
int index;
public Select_(SelectObservable<T, TR> parent, IObserver<TR> observer, IDisposable cancel)
: base(observer, cancel)
{
this.parent = parent;
this.index = 0;
}
public override void OnNext(T value)
{
var v = default(TR);
try
{
v = parent.selectorWithIndex(value, index++);
}
catch (Exception ex)
{
try { observer.OnError(ex); } finally { Dispose(); }
return;
}
observer.OnNext(v);
}
public override void OnError(Exception error)
{
try { observer.OnError(error); } finally { Dispose(); }
}
public override void OnCompleted()
{
try { observer.OnCompleted(); } finally { Dispose(); }
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 997e36ad7b02b804ea1f03d05e60bed5
timeCreated: 1455373900
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,910 @@
using System;
using System.Collections.Generic;
namespace UniRx.Operators
{
internal class SelectManyObservable<TSource, TResult> : OperatorObservableBase<TResult>
{
readonly IObservable<TSource> source;
readonly Func<TSource, IObservable<TResult>> selector;
readonly Func<TSource, int, IObservable<TResult>> selectorWithIndex;
readonly Func<TSource, IEnumerable<TResult>> selectorEnumerable;
readonly Func<TSource, int, IEnumerable<TResult>> selectorEnumerableWithIndex;
public SelectManyObservable(IObservable<TSource> source, Func<TSource, IObservable<TResult>> selector)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.selector = selector;
}
public SelectManyObservable(IObservable<TSource> source, Func<TSource, int, IObservable<TResult>> selector)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.selectorWithIndex = selector;
}
public SelectManyObservable(IObservable<TSource> source, Func<TSource, IEnumerable<TResult>> selector)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.selectorEnumerable = selector;
}
public SelectManyObservable(IObservable<TSource> source, Func<TSource, int, IEnumerable<TResult>> selector)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.selectorEnumerableWithIndex = selector;
}
protected override IDisposable SubscribeCore(IObserver<TResult> observer, IDisposable cancel)
{
if (this.selector != null)
{
return new SelectManyOuterObserver(this, observer, cancel).Run();
}
else if (this.selectorWithIndex != null)
{
return new SelectManyObserverWithIndex(this, observer, cancel).Run();
}
else if (this.selectorEnumerable != null)
{
return new SelectManyEnumerableObserver(this, observer, cancel).Run();
}
else if (this.selectorEnumerableWithIndex != null)
{
return new SelectManyEnumerableObserverWithIndex(this, observer, cancel).Run();
}
else
{
throw new InvalidOperationException();
}
}
class SelectManyOuterObserver : OperatorObserverBase<TSource, TResult>
{
readonly SelectManyObservable<TSource, TResult> parent;
CompositeDisposable collectionDisposable;
SingleAssignmentDisposable sourceDisposable;
object gate = new object();
bool isStopped = false;
public SelectManyOuterObserver(SelectManyObservable<TSource, TResult> parent, IObserver<TResult> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
collectionDisposable = new CompositeDisposable();
sourceDisposable = new SingleAssignmentDisposable();
collectionDisposable.Add(sourceDisposable);
sourceDisposable.Disposable = parent.source.Subscribe(this);
return collectionDisposable;
}
public override void OnNext(TSource value)
{
IObservable<TResult> nextObservable;
try
{
nextObservable = parent.selector(value);
}
catch (Exception ex)
{
try { observer.OnError(ex); } finally { Dispose(); };
return;
}
var disposable = new SingleAssignmentDisposable();
collectionDisposable.Add(disposable);
var collectionObserver = new SelectMany(this, disposable);
disposable.Disposable = nextObservable.Subscribe(collectionObserver);
}
public override void OnError(Exception error)
{
lock (gate)
{
try { observer.OnError(error); } finally { Dispose(); };
}
}
public override void OnCompleted()
{
isStopped = true;
if (collectionDisposable.Count == 1)
{
lock (gate)
{
try { observer.OnCompleted(); } finally { Dispose(); };
}
}
else
{
sourceDisposable.Dispose();
}
}
class SelectMany : OperatorObserverBase<TResult, TResult>
{
readonly SelectManyOuterObserver parent;
readonly IDisposable cancel;
public SelectMany(SelectManyOuterObserver parent, IDisposable cancel)
: base(parent.observer, cancel)
{
this.parent = parent;
this.cancel = cancel;
}
public override void OnNext(TResult value)
{
lock (parent.gate)
{
base.observer.OnNext(value);
}
}
public override void OnError(Exception error)
{
lock (parent.gate)
{
try { observer.OnError(error); } finally { Dispose(); };
}
}
public override void OnCompleted()
{
parent.collectionDisposable.Remove(cancel);
if (parent.isStopped && parent.collectionDisposable.Count == 1)
{
lock (parent.gate)
{
try { observer.OnCompleted(); } finally { Dispose(); };
}
}
}
}
}
class SelectManyObserverWithIndex : OperatorObserverBase<TSource, TResult>
{
readonly SelectManyObservable<TSource, TResult> parent;
CompositeDisposable collectionDisposable;
int index = 0;
object gate = new object();
bool isStopped = false;
SingleAssignmentDisposable sourceDisposable;
public SelectManyObserverWithIndex(SelectManyObservable<TSource, TResult> parent, IObserver<TResult> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
collectionDisposable = new CompositeDisposable();
sourceDisposable = new SingleAssignmentDisposable();
collectionDisposable.Add(sourceDisposable);
sourceDisposable.Disposable = parent.source.Subscribe(this);
return collectionDisposable;
}
public override void OnNext(TSource value)
{
IObservable<TResult> nextObservable;
try
{
nextObservable = parent.selectorWithIndex(value, index++);
}
catch (Exception ex)
{
try { observer.OnError(ex); } finally { Dispose(); };
return;
}
var disposable = new SingleAssignmentDisposable();
collectionDisposable.Add(disposable);
var collectionObserver = new SelectMany(this, disposable);
disposable.Disposable = nextObservable.Subscribe(collectionObserver);
}
public override void OnError(Exception error)
{
lock (gate)
{
try { observer.OnError(error); } finally { Dispose(); };
}
}
public override void OnCompleted()
{
isStopped = true;
if (collectionDisposable.Count == 1)
{
lock (gate)
{
try { observer.OnCompleted(); } finally { Dispose(); };
}
}
else
{
sourceDisposable.Dispose();
}
}
class SelectMany : OperatorObserverBase<TResult, TResult>
{
readonly SelectManyObserverWithIndex parent;
readonly IDisposable cancel;
public SelectMany(SelectManyObserverWithIndex parent, IDisposable cancel)
: base(parent.observer, cancel)
{
this.parent = parent;
this.cancel = cancel;
}
public override void OnNext(TResult value)
{
lock (parent.gate)
{
base.observer.OnNext(value);
}
}
public override void OnError(Exception error)
{
lock (parent.gate)
{
try { observer.OnError(error); } finally { Dispose(); };
}
}
public override void OnCompleted()
{
parent.collectionDisposable.Remove(cancel);
if (parent.isStopped && parent.collectionDisposable.Count == 1)
{
lock (parent.gate)
{
try { observer.OnCompleted(); } finally { Dispose(); };
}
}
}
}
}
class SelectManyEnumerableObserver : OperatorObserverBase<TSource, TResult>
{
readonly SelectManyObservable<TSource, TResult> parent;
public SelectManyEnumerableObserver(SelectManyObservable<TSource, TResult> parent, IObserver<TResult> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
return parent.source.Subscribe(this);
}
public override void OnNext(TSource value)
{
IEnumerable<TResult> nextEnumerable;
try
{
nextEnumerable = parent.selectorEnumerable(value);
}
catch (Exception ex)
{
try { observer.OnError(ex); } finally { Dispose(); };
return;
}
var e = nextEnumerable.GetEnumerator();
try
{
var hasNext = true;
while (hasNext)
{
hasNext = false;
var current = default(TResult);
try
{
hasNext = e.MoveNext();
if (hasNext)
{
current = e.Current;
}
}
catch (Exception exception)
{
try { observer.OnError(exception); } finally { Dispose(); }
return;
}
if (hasNext)
{
observer.OnNext(current);
}
}
}
finally
{
if (e != null)
{
e.Dispose();
}
}
}
public override void OnError(Exception error)
{
try { observer.OnError(error); } finally { Dispose(); }
}
public override void OnCompleted()
{
try { observer.OnCompleted(); } finally { Dispose(); }
}
}
class SelectManyEnumerableObserverWithIndex : OperatorObserverBase<TSource, TResult>
{
readonly SelectManyObservable<TSource, TResult> parent;
int index = 0;
public SelectManyEnumerableObserverWithIndex(SelectManyObservable<TSource, TResult> parent, IObserver<TResult> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
return parent.source.Subscribe(this);
}
public override void OnNext(TSource value)
{
IEnumerable<TResult> nextEnumerable;
try
{
nextEnumerable = parent.selectorEnumerableWithIndex(value, index++);
}
catch (Exception ex)
{
OnError(ex);
return;
}
var e = nextEnumerable.GetEnumerator();
try
{
var hasNext = true;
while (hasNext)
{
hasNext = false;
var current = default(TResult);
try
{
hasNext = e.MoveNext();
if (hasNext)
{
current = e.Current;
}
}
catch (Exception exception)
{
try { observer.OnError(exception); } finally { Dispose(); }
return;
}
if (hasNext)
{
observer.OnNext(current);
}
}
}
finally
{
if (e != null)
{
e.Dispose();
}
}
}
public override void OnError(Exception error)
{
try { observer.OnError(error); } finally { Dispose(); }
}
public override void OnCompleted()
{
try { observer.OnCompleted(); } finally { Dispose(); }
}
}
}
// with resultSelector
internal class SelectManyObservable<TSource, TCollection, TResult> : OperatorObservableBase<TResult>
{
readonly IObservable<TSource> source;
readonly Func<TSource, IObservable<TCollection>> collectionSelector;
readonly Func<TSource, int, IObservable<TCollection>> collectionSelectorWithIndex;
readonly Func<TSource, IEnumerable<TCollection>> collectionSelectorEnumerable;
readonly Func<TSource, int, IEnumerable<TCollection>> collectionSelectorEnumerableWithIndex;
readonly Func<TSource, TCollection, TResult> resultSelector;
readonly Func<TSource, int, TCollection, int, TResult> resultSelectorWithIndex;
public SelectManyObservable(IObservable<TSource> source, Func<TSource, IObservable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.collectionSelector = collectionSelector;
this.resultSelector = resultSelector;
}
public SelectManyObservable(IObservable<TSource> source, Func<TSource, int, IObservable<TCollection>> collectionSelector, Func<TSource, int, TCollection, int, TResult> resultSelector)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.collectionSelectorWithIndex = collectionSelector;
this.resultSelectorWithIndex = resultSelector;
}
public SelectManyObservable(IObservable<TSource> source, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.collectionSelectorEnumerable = collectionSelector;
this.resultSelector = resultSelector;
}
public SelectManyObservable(IObservable<TSource> source, Func<TSource, int, IEnumerable<TCollection>> collectionSelector, Func<TSource, int, TCollection, int, TResult> resultSelector)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.collectionSelectorEnumerableWithIndex = collectionSelector;
this.resultSelectorWithIndex = resultSelector;
}
protected override IDisposable SubscribeCore(IObserver<TResult> observer, IDisposable cancel)
{
if (collectionSelector != null)
{
return new SelectManyOuterObserver(this, observer, cancel).Run();
}
else if (collectionSelectorWithIndex != null)
{
return new SelectManyObserverWithIndex(this, observer, cancel).Run();
}
else if (collectionSelectorEnumerable != null)
{
return new SelectManyEnumerableObserver(this, observer, cancel).Run();
}
else if (collectionSelectorEnumerableWithIndex != null)
{
return new SelectManyEnumerableObserverWithIndex(this, observer, cancel).Run();
}
else
{
throw new InvalidOperationException();
}
}
class SelectManyOuterObserver : OperatorObserverBase<TSource, TResult>
{
readonly SelectManyObservable<TSource, TCollection, TResult> parent;
CompositeDisposable collectionDisposable;
object gate = new object();
bool isStopped = false;
SingleAssignmentDisposable sourceDisposable;
public SelectManyOuterObserver(SelectManyObservable<TSource, TCollection, TResult> parent, IObserver<TResult> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
collectionDisposable = new CompositeDisposable();
sourceDisposable = new SingleAssignmentDisposable();
collectionDisposable.Add(sourceDisposable);
sourceDisposable.Disposable = parent.source.Subscribe(this);
return collectionDisposable;
}
public override void OnNext(TSource value)
{
IObservable<TCollection> nextObservable;
try
{
nextObservable = parent.collectionSelector(value);
}
catch (Exception ex)
{
OnError(ex);
return;
}
var disposable = new SingleAssignmentDisposable();
collectionDisposable.Add(disposable);
var collectionObserver = new SelectMany(this, value, disposable);
disposable.Disposable = nextObservable.Subscribe(collectionObserver);
}
public override void OnError(Exception error)
{
lock (gate)
{
try { observer.OnError(error); } finally { Dispose(); };
}
}
public override void OnCompleted()
{
isStopped = true;
if (collectionDisposable.Count == 1)
{
lock (gate)
{
try { observer.OnCompleted(); } finally { Dispose(); };
}
}
else
{
sourceDisposable.Dispose();
}
}
class SelectMany : OperatorObserverBase<TCollection, TResult>
{
readonly SelectManyOuterObserver parent;
readonly TSource sourceValue;
readonly IDisposable cancel;
public SelectMany(SelectManyOuterObserver parent, TSource value, IDisposable cancel)
: base(parent.observer, cancel)
{
this.parent = parent;
this.sourceValue = value;
this.cancel = cancel;
}
public override void OnNext(TCollection value)
{
TResult resultValue;
try
{
resultValue = parent.parent.resultSelector(sourceValue, value);
}
catch (Exception ex)
{
OnError(ex);
return;
}
lock (parent.gate)
{
base.observer.OnNext(resultValue);
}
}
public override void OnError(Exception error)
{
lock (parent.gate)
{
try { observer.OnError(error); } finally { Dispose(); };
}
}
public override void OnCompleted()
{
parent.collectionDisposable.Remove(cancel);
if (parent.isStopped && parent.collectionDisposable.Count == 1)
{
lock (parent.gate)
{
try { observer.OnCompleted(); } finally { Dispose(); };
}
}
}
}
}
class SelectManyObserverWithIndex : OperatorObserverBase<TSource, TResult>
{
readonly SelectManyObservable<TSource, TCollection, TResult> parent;
CompositeDisposable collectionDisposable;
object gate = new object();
bool isStopped = false;
SingleAssignmentDisposable sourceDisposable;
int index = 0;
public SelectManyObserverWithIndex(SelectManyObservable<TSource, TCollection, TResult> parent, IObserver<TResult> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
collectionDisposable = new CompositeDisposable();
sourceDisposable = new SingleAssignmentDisposable();
collectionDisposable.Add(sourceDisposable);
sourceDisposable.Disposable = parent.source.Subscribe(this);
return collectionDisposable;
}
public override void OnNext(TSource value)
{
var i = index++;
IObservable<TCollection> nextObservable;
try
{
nextObservable = parent.collectionSelectorWithIndex(value, i);
}
catch (Exception ex)
{
OnError(ex);
return;
}
var disposable = new SingleAssignmentDisposable();
collectionDisposable.Add(disposable);
var collectionObserver = new SelectManyObserver(this, value, i, disposable);
disposable.Disposable = nextObservable.Subscribe(collectionObserver);
}
public override void OnError(Exception error)
{
lock (gate)
{
try { observer.OnError(error); } finally { Dispose(); };
}
}
public override void OnCompleted()
{
isStopped = true;
if (collectionDisposable.Count == 1)
{
lock (gate)
{
try { observer.OnCompleted(); } finally { Dispose(); };
}
}
else
{
sourceDisposable.Dispose();
}
}
class SelectManyObserver : OperatorObserverBase<TCollection, TResult>
{
readonly SelectManyObserverWithIndex parent;
readonly TSource sourceValue;
readonly int sourceIndex;
readonly IDisposable cancel;
int index;
public SelectManyObserver(SelectManyObserverWithIndex parent, TSource value, int index, IDisposable cancel)
: base(parent.observer, cancel)
{
this.parent = parent;
this.sourceValue = value;
this.sourceIndex = index;
this.cancel = cancel;
}
public override void OnNext(TCollection value)
{
TResult resultValue;
try
{
resultValue = parent.parent.resultSelectorWithIndex(sourceValue, sourceIndex, value, index++);
}
catch (Exception ex)
{
try { observer.OnError(ex); } finally { Dispose(); };
return;
}
lock (parent.gate)
{
base.observer.OnNext(resultValue);
}
}
public override void OnError(Exception error)
{
lock (parent.gate)
{
try { observer.OnError(error); } finally { Dispose(); };
}
}
public override void OnCompleted()
{
parent.collectionDisposable.Remove(cancel);
if (parent.isStopped && parent.collectionDisposable.Count == 1)
{
lock (parent.gate)
{
try { observer.OnCompleted(); } finally { Dispose(); };
}
}
}
}
}
class SelectManyEnumerableObserver : OperatorObserverBase<TSource, TResult>
{
readonly SelectManyObservable<TSource, TCollection, TResult> parent;
public SelectManyEnumerableObserver(SelectManyObservable<TSource, TCollection, TResult> parent, IObserver<TResult> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
return parent.source.Subscribe(this);
}
public override void OnNext(TSource value)
{
IEnumerable<TCollection> nextEnumerable;
try
{
nextEnumerable = parent.collectionSelectorEnumerable(value);
}
catch (Exception ex)
{
try { observer.OnError(ex); } finally { Dispose(); };
return;
}
var e = nextEnumerable.GetEnumerator();
try
{
var hasNext = true;
while (hasNext)
{
hasNext = false;
var current = default(TResult);
try
{
hasNext = e.MoveNext();
if (hasNext)
{
current = parent.resultSelector(value, e.Current);
}
}
catch (Exception exception)
{
try { observer.OnError(exception); } finally { Dispose(); }
return;
}
if (hasNext)
{
observer.OnNext(current);
}
}
}
finally
{
if (e != null)
{
e.Dispose();
}
}
}
public override void OnError(Exception error)
{
try { observer.OnError(error); } finally { Dispose(); }
}
public override void OnCompleted()
{
try { observer.OnCompleted(); } finally { Dispose(); }
}
}
class SelectManyEnumerableObserverWithIndex : OperatorObserverBase<TSource, TResult>
{
readonly SelectManyObservable<TSource, TCollection, TResult> parent;
int index = 0;
public SelectManyEnumerableObserverWithIndex(SelectManyObservable<TSource, TCollection, TResult> parent, IObserver<TResult> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
return parent.source.Subscribe(this);
}
public override void OnNext(TSource value)
{
var i = index++;
IEnumerable<TCollection> nextEnumerable;
try
{
nextEnumerable = parent.collectionSelectorEnumerableWithIndex(value, i);
}
catch (Exception ex)
{
try { observer.OnError(ex); } finally { Dispose(); };
return;
}
var e = nextEnumerable.GetEnumerator();
try
{
var sequenceI = 0;
var hasNext = true;
while (hasNext)
{
hasNext = false;
var current = default(TResult);
try
{
hasNext = e.MoveNext();
if (hasNext)
{
current = parent.resultSelectorWithIndex(value, i, e.Current, sequenceI++);
}
}
catch (Exception exception)
{
try { observer.OnError(exception); } finally { Dispose(); }
return;
}
if (hasNext)
{
observer.OnNext(current);
}
}
}
finally
{
if (e != null)
{
e.Dispose();
}
}
}
public override void OnError(Exception error)
{
try { observer.OnError(error); } finally { Dispose(); }
}
public override void OnCompleted()
{
try { observer.OnCompleted(); } finally { Dispose(); }
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 6496e8557f6066e4380c32935b6f37c3
timeCreated: 1455373899
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,77 @@
using System;
namespace UniRx.Operators
{
// Optimize for .Select().Where()
internal class SelectWhereObservable<T, TR> : OperatorObservableBase<TR>
{
readonly IObservable<T> source;
readonly Func<T, TR> selector;
readonly Func<TR, bool> predicate;
public SelectWhereObservable(IObservable<T> source, Func<T, TR> selector, Func<TR, bool> predicate)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.selector = selector;
this.predicate = predicate;
}
protected override IDisposable SubscribeCore(IObserver<TR> observer, IDisposable cancel)
{
return source.Subscribe(new SelectWhere(this, observer, cancel));
}
class SelectWhere : OperatorObserverBase<T, TR>
{
readonly SelectWhereObservable<T, TR> parent;
public SelectWhere(SelectWhereObservable<T, TR> parent, IObserver<TR> observer, IDisposable cancel)
: base(observer, cancel)
{
this.parent = parent;
}
public override void OnNext(T value)
{
var v = default(TR);
try
{
v = parent.selector(value);
}
catch (Exception ex)
{
try { observer.OnError(ex); } finally { Dispose(); }
return;
}
var isPassed = false;
try
{
isPassed = parent.predicate(v);
}
catch (Exception ex)
{
try { observer.OnError(ex); } finally { Dispose(); }
return;
}
if (isPassed)
{
observer.OnNext(v);
}
}
public override void OnError(Exception error)
{
try { observer.OnError(error); } finally { Dispose(); }
}
public override void OnCompleted()
{
try { observer.OnCompleted(); } finally { Dispose(); }
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 6a7561d10967d6b4d9c2a67ffc3b9d85
timeCreated: 1468748731
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,182 @@
using System;
namespace UniRx.Operators
{
internal class SingleObservable<T> : OperatorObservableBase<T>
{
readonly IObservable<T> source;
readonly bool useDefault;
readonly Func<T, bool> predicate;
public SingleObservable(IObservable<T> source, bool useDefault)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.useDefault = useDefault;
}
public SingleObservable(IObservable<T> source, Func<T, bool> predicate, bool useDefault)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.predicate = predicate;
this.useDefault = useDefault;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
if (predicate == null)
{
return source.Subscribe(new Single(this, observer, cancel));
}
else
{
return source.Subscribe(new Single_(this, observer, cancel));
}
}
class Single : OperatorObserverBase<T, T>
{
readonly SingleObservable<T> parent;
bool seenValue;
T lastValue;
public Single(SingleObservable<T> parent, IObserver<T> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
this.seenValue = false;
}
public override void OnNext(T value)
{
if (seenValue)
{
try { observer.OnError(new InvalidOperationException("sequence is not single")); }
finally { Dispose(); }
}
else
{
seenValue = true;
lastValue = value;
}
}
public override void OnError(Exception error)
{
try { observer.OnError(error); }
finally { Dispose(); }
}
public override void OnCompleted()
{
if (parent.useDefault)
{
if (!seenValue)
{
observer.OnNext(default(T));
}
else
{
observer.OnNext(lastValue);
}
try { observer.OnCompleted(); }
finally { Dispose(); }
}
else
{
if (!seenValue)
{
try { observer.OnError(new InvalidOperationException("sequence is empty")); }
finally { Dispose(); }
}
else
{
observer.OnNext(lastValue);
try { observer.OnCompleted(); }
finally { Dispose(); }
}
}
}
}
class Single_ : OperatorObserverBase<T, T>
{
readonly SingleObservable<T> parent;
bool seenValue;
T lastValue;
public Single_(SingleObservable<T> parent, IObserver<T> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
this.seenValue = false;
}
public override void OnNext(T value)
{
bool isPassed;
try
{
isPassed = parent.predicate(value);
}
catch (Exception ex)
{
try { observer.OnError(ex); }
finally { Dispose(); }
return;
}
if (isPassed)
{
if (seenValue)
{
try { observer.OnError(new InvalidOperationException("sequence is not single")); }
finally { Dispose(); }
return;
}
else
{
seenValue = true;
lastValue = value;
}
}
}
public override void OnError(Exception error)
{
try { observer.OnError(error); }
finally { Dispose(); }
}
public override void OnCompleted()
{
if (parent.useDefault)
{
if (!seenValue)
{
observer.OnNext(default(T));
}
else
{
observer.OnNext(lastValue);
}
try { observer.OnCompleted(); }
finally { Dispose(); }
}
else
{
if (!seenValue)
{
try { observer.OnError(new InvalidOperationException("sequence is empty")); }
finally { Dispose(); }
}
else
{
observer.OnNext(lastValue);
try { observer.OnCompleted(); }
finally { Dispose(); }
}
}
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 9a50aee929f403f4ea076fc11f71fc53
timeCreated: 1455373900
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,138 @@
using System;
using UniRx.Operators;
namespace UniRx.Operators
{
internal class SkipObservable<T> : OperatorObservableBase<T>
{
readonly IObservable<T> source;
readonly int count;
readonly TimeSpan duration;
internal readonly IScheduler scheduler; // public for optimization check
public SkipObservable(IObservable<T> source, int count)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.count = count;
}
public SkipObservable(IObservable<T> source, TimeSpan duration, IScheduler scheduler)
: base(scheduler == Scheduler.CurrentThread || source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.duration = duration;
this.scheduler = scheduler;
}
// optimize combiner
public IObservable<T> Combine(int count)
{
// use sum
// xs = 6
// xs.Skip(2) = 4
// xs.Skip(2).Skip(3) = 1
return new SkipObservable<T>(source, this.count + count);
}
public IObservable<T> Combine(TimeSpan duration)
{
// use max
// xs = 6s
// xs.Skip(2s) = 2s
// xs.Skip(2s).Skip(3s) = 3s
return (duration <= this.duration)
? this
: new SkipObservable<T>(source, duration, scheduler);
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
if (scheduler == null)
{
return source.Subscribe(new Skip(this, observer, cancel));
}
else
{
return new Skip_(this, observer, cancel).Run();
}
}
class Skip : OperatorObserverBase<T, T>
{
int remaining;
public Skip(SkipObservable<T> parent, IObserver<T> observer, IDisposable cancel) : base(observer, cancel)
{
this.remaining = parent.count;
}
public override void OnNext(T value)
{
if (remaining <= 0)
{
base.observer.OnNext(value);
}
else
{
remaining--;
}
}
public override void OnError(Exception error)
{
try { observer.OnError(error); } finally { Dispose(); }
}
public override void OnCompleted()
{
try { observer.OnCompleted(); } finally { Dispose(); }
}
}
class Skip_ : OperatorObserverBase<T, T>
{
readonly SkipObservable<T> parent;
volatile bool open;
public Skip_(SkipObservable<T> parent, IObserver<T> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
var d1 = parent.scheduler.Schedule(parent.duration, Tick);
var d2 = parent.source.Subscribe(this);
return StableCompositeDisposable.Create(d1, d2);
}
void Tick()
{
open = true;
}
public override void OnNext(T value)
{
if (open)
{
base.observer.OnNext(value);
}
}
public override void OnError(Exception error)
{
try { observer.OnError(error); } finally { Dispose(); };
}
public override void OnCompleted()
{
try { observer.OnCompleted(); } finally { Dispose(); };
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 1ffcb45c02e14e94bb37c6513b04bb7c
timeCreated: 1455373897
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,119 @@
using System;
namespace UniRx.Operators
{
internal class SkipUntilObservable<T, TOther> : OperatorObservableBase<T>
{
readonly IObservable<T> source;
readonly IObservable<TOther> other;
public SkipUntilObservable(IObservable<T> source, IObservable<TOther> other)
: base(source.IsRequiredSubscribeOnCurrentThread() || other.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.other = other;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
return new SkipUntilOuterObserver(this, observer, cancel).Run();
}
class SkipUntilOuterObserver : OperatorObserverBase<T, T>
{
readonly SkipUntilObservable<T, TOther> parent;
public SkipUntilOuterObserver(SkipUntilObservable<T, TOther> parent, IObserver<T> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
var sourceSubscription = new SingleAssignmentDisposable();
var sourceObserver = new SkipUntil(this, sourceSubscription);
var otherSubscription = new SingleAssignmentDisposable();
var otherObserver = new SkipUntilOther(this, sourceObserver, otherSubscription);
sourceSubscription.Disposable = parent.source.Subscribe(sourceObserver);
otherSubscription.Disposable = parent.other.Subscribe(otherObserver);
return StableCompositeDisposable.Create(otherSubscription, sourceSubscription);
}
public override void OnNext(T value)
{
}
public override void OnError(Exception error)
{
}
public override void OnCompleted()
{
}
class SkipUntil : IObserver<T>
{
public volatile IObserver<T> observer;
readonly SkipUntilOuterObserver parent;
readonly IDisposable subscription;
public SkipUntil(SkipUntilOuterObserver parent, IDisposable subscription)
{
this.parent = parent;
observer = UniRx.InternalUtil.EmptyObserver<T>.Instance;
this.subscription = subscription;
}
public void OnNext(T value)
{
observer.OnNext(value);
}
public void OnError(Exception error)
{
try { observer.OnError(error); }
finally { parent.Dispose(); }
}
public void OnCompleted()
{
try { observer.OnCompleted(); }
finally { subscription.Dispose(); }
}
}
class SkipUntilOther : IObserver<TOther>
{
readonly SkipUntilOuterObserver parent;
readonly SkipUntil sourceObserver;
readonly IDisposable subscription;
public SkipUntilOther(SkipUntilOuterObserver parent, SkipUntil sourceObserver, IDisposable subscription)
{
this.parent = parent;
this.sourceObserver = sourceObserver;
this.subscription = subscription;
}
public void OnNext(TOther value)
{
sourceObserver.observer = parent.observer;
subscription.Dispose();
}
public void OnError(Exception error)
{
try { parent.observer.OnError(error); } finally { parent.Dispose(); }
}
public void OnCompleted()
{
subscription.Dispose();
}
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 52314487e375f3d44a49bc5ceb90adab
timeCreated: 1455373899
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,130 @@
using System;
namespace UniRx.Operators
{
internal class SkipWhileObservable<T> : OperatorObservableBase<T>
{
readonly IObservable<T> source;
readonly Func<T, bool> predicate;
readonly Func<T, int, bool> predicateWithIndex;
public SkipWhileObservable(IObservable<T> source, Func<T, bool> predicate)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.predicate = predicate;
}
public SkipWhileObservable(IObservable<T> source, Func<T, int, bool> predicateWithIndex)
: base(source.IsRequiredSubscribeOnCurrentThread())
{
this.source = source;
this.predicateWithIndex = predicateWithIndex;
}
protected override IDisposable SubscribeCore(IObserver<T> observer, IDisposable cancel)
{
if (predicate != null)
{
return new SkipWhile(this, observer, cancel).Run();
}
else
{
return new SkipWhile_(this, observer, cancel).Run();
}
}
class SkipWhile : OperatorObserverBase<T, T>
{
readonly SkipWhileObservable<T> parent;
bool endSkip = false;
public SkipWhile(SkipWhileObservable<T> parent, IObserver<T> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
return parent.source.Subscribe(this);
}
public override void OnNext(T value)
{
if (!endSkip)
{
try
{
endSkip = !parent.predicate(value);
}
catch (Exception ex)
{
try { observer.OnError(ex); } finally { Dispose(); }
return;
}
if (!endSkip) return;
}
observer.OnNext(value);
}
public override void OnError(Exception error)
{
try { observer.OnError(error); } finally { Dispose(); }
}
public override void OnCompleted()
{
try { observer.OnCompleted(); } finally { Dispose(); }
}
}
class SkipWhile_ : OperatorObserverBase<T, T>
{
readonly SkipWhileObservable<T> parent;
bool endSkip = false;
int index = 0;
public SkipWhile_(SkipWhileObservable<T> parent, IObserver<T> observer, IDisposable cancel) : base(observer, cancel)
{
this.parent = parent;
}
public IDisposable Run()
{
return parent.source.Subscribe(this);
}
public override void OnNext(T value)
{
if (!endSkip)
{
try
{
endSkip = !parent.predicateWithIndex(value, index++);
}
catch (Exception ex)
{
try { observer.OnError(ex); } finally { Dispose(); }
return;
}
if (!endSkip) return;
}
observer.OnNext(value);
}
public override void OnError(Exception error)
{
try { observer.OnError(error); } finally { Dispose(); }
}
public override void OnCompleted()
{
try { observer.OnCompleted(); } finally { Dispose(); }
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 4bc7a1e818d05654694d51e883739cca
timeCreated: 1455373898
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Some files were not shown because too many files have changed in this diff Show More